LAPTOP-SNT8I5JK\Boounion
2025-05-30 405bd36e812c3645e8d9d84700777e2eaeb036ec
Merge branch 'clh'

# Conflicts:
# SourceCode/Bond/Servo/Servo.rc
# SourceCode/Bond/Servo/Servo.vcxproj
# SourceCode/Bond/Servo/Servo.vcxproj.filters
# SourceCode/Bond/Servo/resource.h
已添加13个文件
已修改77个文件
2944 ■■■■ 文件已修改
Document/BONDER流程信息表.xls 补丁 | 查看 | 原始文档 | blame | 历史
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6(1).xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6(5).xlsx 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CAligner.cpp 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CAligner.h 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CArm.cpp 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CArm.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CArmTray.cpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CArmTray.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CAttribute.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CAttributeVector.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBakeCooling.cpp 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBakeCooling.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBonder.cpp 74 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBonder.h 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEFEM.cpp 76 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEFEM.h 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqAlarmStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqCassetteTransferStateStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqCimMessageClearStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqCimMessageCmdStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqCimModeChangeStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqJobEventStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqModeChangeStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqModeStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqPortChangeStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqProcessStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqReadIntStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqReadStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqStatusStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqVCREnableStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqVcrEventStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEqWriteStep.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.cpp 409 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.h 116 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipmentPage2.cpp 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CFliper.cpp 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CFliper.h 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CGlassPool.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CJobDataA.cpp 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CJobDataA.h 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CJobDataB.cpp 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CJobDataB.h 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CJobDataC.cpp 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CJobDataC.h 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CJobDataS.cpp 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CJobDataS.h 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CLoadPort.cpp 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CLoadPort.h 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp 347 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.h 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMeasurement.cpp 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMeasurement.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMyStatusbar.cpp 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMyStatusbar.h 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageGraph2.cpp 71 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPagePortProperty.cpp 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPath.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPin.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPortStatusReport.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CProcessData.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotCmdTestDlg.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotTask.cpp 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotTask.h 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CSlot.cpp 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CSlot.h 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVacuumBake.cpp 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVacuumBake.h 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CVcrEventReport.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Common.h 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Model.cpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Model.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.cpp 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.filters 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoCommo.h 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.cpp 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.h 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ToolUnits.cpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/TopToolbar.cpp 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/TopToolbar.h 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Master.dat 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/robot_Gray_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/Debug/Res/robot_High_32.ico 补丁 | 查看 | 原始文档 | blame | 历史
Document/BONDERÁ÷³ÌÐÅÏ¢±í.xls
Binary files differ
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6(1).xlsx
Binary files differ
Document/ESWIN_EAS_Bonder_Inline_Mapping_Address_v1.1.6(5).xlsx
Binary files differ
SourceCode/Bond/Servo/CAligner.cpp
@@ -39,6 +39,15 @@
        addPin(SERVO::PinType::OUTPUT, _T("Out2"));
    }
    // å¿…须要实现的虚函数,在此初始化Slot信息
    void CAligner::initSlots()
    {
        m_slot[0].enable();
        m_slot[0].setPosition(m_nID);
        m_slot[0].setNo(1);
        m_slot[0].setName("Slot 1");
    }
    void CAligner::onTimer(UINT nTimerid)
    {
        CEquipment::onTimer(nTimerid);
@@ -57,35 +66,5 @@
    int CAligner::recvIntent(CPin* pPin, CIntent* pIntent)
    {
        return __super::recvIntent(pPin, pIntent);
    }
    BOOL CAligner::glassWillArrive(CGlass* pGlass)
    {
        BOOL bRet = __super::glassWillArrive(pGlass);
        if (!bRet) {
            return FALSE;
        }
        return m_glassList.empty();
    }
    BOOL CAligner::onPreStoredJob(int port, CJobDataB* pJobDataB)
    {
        CJobDataS* pJobDataS = getJobDataS(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
        if (pJobDataS == nullptr) {
            LOGE("<CAligner-%s>onPreFetchedOutJob,找不到对应的JobDataS(CassetteSequenceNo:%d, JobSequenceNo:%d), æ³¨æ„æŽ’查风险!", m_strName.c_str(),
                pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
            return FALSE;
        }
        // åªèƒ½ä¸€ç‰‡ä¸€ç‰‡çš„对位
        Lock();
        if (!m_glassList.empty()) {
            Unlock();
            LOGE("<CEquipment-%s>onPreFetchedOutJob,当前机器或单元存在玻璃片,不能进料,请注意风险!", m_strName.c_str());
            return FALSE;
        }
        return TRUE;
    }
}
SourceCode/Bond/Servo/CAligner.h
@@ -15,12 +15,11 @@
        virtual void init();
        virtual void term();
        virtual void initPins();
        virtual void initSlots();
        virtual void onTimer(UINT nTimerid);
        virtual void serialize(CArchive& ar);
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual BOOL glassWillArrive(CGlass* pGlass);
        virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
    };
}
SourceCode/Bond/Servo/CArm.cpp
@@ -34,6 +34,19 @@
    }
    // å¿…须要实现的虚函数,在此初始化Slot信息
    void CArm::initSlots()
    {
        m_slot[0].enable();
        m_slot[0].setPosition(m_nID);
        m_slot[0].setNo(1);
        m_slot[0].setName("Slot 1(Temp)");
        m_slot[1].enable();
        m_slot[1].setPosition(m_nID);
        m_slot[1].setNo(2);
        m_slot[1].setName("Slot 2(Temp)");
    }
    void CArm::onTimer(UINT nTimerid)
    {
        CEquipment::onTimer(nTimerid);
@@ -59,13 +72,19 @@
        // åŽŸï¼šä¿è¯åˆ—è¡¨ä¸­åªå­˜å‚¨ä¸€ä¸ªç‰©æ–™
        // ä¿®æ”¹ä¸ºï¼šå…ˆæ¸…空之前的,再添加当前pGlass, å¦‚æžœpGlass有buddy,也要加入列表中
        Lock();
        for (auto item : m_glassList) {
            item->release();
        CGlass* pPreviousGlass;
        pPreviousGlass = (CGlass*)m_slot[0].getContext();
        if (pPreviousGlass != nullptr) {
            pPreviousGlass->release();
        }
        m_glassList.clear();
        addGlassToList(pGlass);
        pPreviousGlass = (CGlass*)m_slot[1].getContext();
        if (pPreviousGlass != nullptr) {
            pPreviousGlass->release();
        }
        m_slot[0].setContext(pGlass);
        if (pGlass->getBuddy() != nullptr) {
            addGlassToList(pGlass->getBuddy());
            m_slot[1].setContext(pGlass->getBuddy());
        }
        Unlock();
@@ -79,17 +98,14 @@
    int CArm::tempFetchOut(OUT CGlass*& pGlass)
    {
        Lock();
        if (m_glassList.empty()) {
        CGlass* pPreviousGlass = (CGlass*)m_slot[0].getContext();
        if (pPreviousGlass == nullptr) {
            Unlock();
            return -1;
        }
        pGlass = m_glassList.front();
        pGlass = pPreviousGlass;
        pGlass->addRef();
        for (auto item : m_glassList) {
            item->release();
        }
        m_glassList.clear();
        m_slot[0].setContext(nullptr);
        Unlock();
        if (m_listener.onDataChanged != nullptr) {
SourceCode/Bond/Servo/CArm.h
@@ -15,6 +15,7 @@
        virtual void init();
        virtual void term();
        virtual void initPins();
        virtual void initSlots();
        virtual void onTimer(UINT nTimerid);
        virtual void serialize(CArchive& ar);
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CArmTray.cpp
@@ -34,6 +34,15 @@
    }
    // å¿…须要实现的虚函数,在此初始化Slot信息
    void CArmTray::initSlots()
    {
        m_slot[0].enable();
        m_slot[0].setPosition(m_nID);
        m_slot[0].setNo(1);
        m_slot[0].setName("Slot 1");
    }
    void CArmTray::onTimer(UINT nTimerid)
    {
        CEquipment::onTimer(nTimerid);
SourceCode/Bond/Servo/CArmTray.h
@@ -14,6 +14,7 @@
        virtual void init();
        virtual void term();
        virtual void initPins();
        virtual void initSlots();
        virtual void onTimer(UINT nTimerid);
        virtual void serialize(CArchive& ar);
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CAttribute.h
@@ -7,7 +7,7 @@
    public:
        CAttribute();
        CAttribute(const char* pszName, const char* pszValue, const char* pszDescription, unsigned int weight);
        ~CAttribute();
        virtual ~CAttribute();
    public:
        std::string& getName();
SourceCode/Bond/Servo/CAttributeVector.h
@@ -8,7 +8,7 @@
    {
    public:
        CAttributeVector();
        ~CAttributeVector();
        virtual ~CAttributeVector();
    public:
        void addAttribute(CAttribute* pAttribute, BOOL bReplace = FALSE);
SourceCode/Bond/Servo/CBakeCooling.cpp
@@ -38,6 +38,15 @@
        addPin(SERVO::PinType::OUTPUT, _T("Out"));
    }
    // å¿…须要实现的虚函数,在此初始化Slot信息
    void CBakeCooling::initSlots()
    {
        m_slot[0].enable();
        m_slot[0].setPosition(m_nID);
        m_slot[0].setNo(1);
        m_slot[0].setName("Slot 1");
    }
    void CBakeCooling::onTimer(UINT nTimerid)
    {
        CEquipment::onTimer(nTimerid);
@@ -56,16 +65,6 @@
    int CBakeCooling::recvIntent(CPin* pPin, CIntent* pIntent)
    {
        return __super::recvIntent(pPin, pIntent);
    }
    BOOL CBakeCooling::glassWillArrive(CGlass* pGlass)
    {
        BOOL bRet = __super::glassWillArrive(pGlass);
        if (!bRet) {
            return FALSE;
        }
        return (m_glassList.size() < 4);
    }
    int CBakeCooling::getIndexerOperationModeBaseValue()
SourceCode/Bond/Servo/CBakeCooling.h
@@ -15,11 +15,11 @@
        virtual void init();
        virtual void term();
        virtual void initPins();
        virtual void initSlots();
        virtual void onTimer(UINT nTimerid);
        virtual void serialize(CArchive& ar);
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual BOOL glassWillArrive(CGlass* pGlass);
        virtual int getIndexerOperationModeBaseValue();
    };
}
SourceCode/Bond/Servo/CBonder.cpp
@@ -336,6 +336,21 @@
        }
    }
    // å¿…须要实现的虚函数,在此初始化Slot信息
    void CBonder::initSlots()
    {
        m_slot[0].enable();
        m_slot[0].setPosition(m_nID);
        m_slot[0].setNo(1);
        m_slot[0].setName("Slot 1(G1)");
        m_slot[0].setType(MaterialsType::G1);
        m_slot[1].enable();
        m_slot[1].setPosition(m_nID);
        m_slot[1].setNo(2);
        m_slot[1].setName("Slot 2(G2)");
        m_slot[1].setType(MaterialsType::G2);
    }
    void CBonder::onTimer(UINT nTimerid)
    {
        CEquipment::onTimer(nTimerid);
@@ -356,16 +371,6 @@
        return __super::recvIntent(pPin, pIntent);
    }
    BOOL CBonder::glassWillArrive(CGlass* pGlass)
    {
        BOOL bRet = __super::glassWillArrive(pGlass);
        if (!bRet) {
            return FALSE;
        }
        return m_glassList.empty();
    }
    void CBonder::setIndex(unsigned int index)
    {
        m_nIndex = index;
@@ -376,39 +381,6 @@
        return m_nIndex;
    }
    BOOL CBonder::onPreStoredJob(int port, CJobDataB* pJobDataB)
    {
        CJobDataS* pJobDataS = getJobDataS(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
        if (pJobDataS == nullptr) {
            LOGE("<CBonder-%s>onPreFetchedOutJob,找不到对应的JobDataS(CassetteSequenceNo:%d, JobSequenceNo:%d), æ³¨æ„æŽ’查风险!", m_strName.c_str(),
                pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
            return FALSE;
        }
        // å¦‚果为空,可以进G1或G2
        // å¦‚果有一片玻璃,当前玻璃为G1则可进G2, å½“前玻璃为G2则可进G1
        BOOL bCheck = FALSE;
        Lock();
        size_t size = m_glassList.size();
        if (size == 0) {
            bCheck = TRUE;
        }
        else if (size == 1) {
            CGlass* pGlass = m_glassList.front();
            if ((pGlass->getType() == MaterialsType::G1 && pJobDataS->getMaterialsType() == (int)MaterialsType::G2)
                || (pGlass->getType() == MaterialsType::G2 && pJobDataS->getMaterialsType() == (int)MaterialsType::G1)) {
                bCheck = TRUE;
            }
        }
        Unlock();
        if (!bCheck) {
            LOGE("<CEquipment-%s>onPreFetchedOutJob,当前机器不满足进料条件,或已存在两片玻璃,或G2与G1不匹配,请注意风险!", m_strName.c_str());
        }
        return bCheck;
    }
    int CBonder::onProcessData(CProcessData* pProcessData)
    {
        CEquipment::onProcessData(pProcessData);
@@ -416,28 +388,23 @@
        // æ£€æŸ¥æ•°æ®ï¼Œå½“前两片玻璃,一片为G1, ä¸€ç‰‡ä¸ºG2, ä¸”pProcessData中的id能匹配G1或G2
        Lock();
        if (m_glassList.size() != 2) {
            Unlock();
            LOGE("<CBonder-%s>onProcessData,绑定失败,腔体内必须有且仅有两片玻璃!", m_strName.c_str());
            return -1;
        }
        CGlass* pGlass1 = m_glassList.front();
        CGlass* pGlass2 = m_glassList.back();
        Unlock();
        CGlass* pGlass1 = getGlassFromSlot(1);
        CGlass* pGlass2 = getGlassFromSlot(2);
        if (pGlass1->getBuddy() != nullptr || pGlass2->getBuddy() != nullptr) {
            LOGE("<CBonder-%s>onProcessData,错误!玻璃较早前已被绑定,请检查数据是否正确!", m_strName.c_str());
            Unlock();
            return -1;
        }
        if (pGlass1->getBuddy() != nullptr || pGlass2->getBuddy() != nullptr) {
            LOGE("<CBonder-%s>onProcessData,错误!玻璃较早前已被贴合,请检查数据是否正确!", m_strName.c_str());
            Unlock();
            return -1;
        }
        if (pGlass1->getType() == pGlass2->getType()) {
            LOGE("<CBonder-%s>onProcessData,错误!两片玻璃未匹配,必须分别为G1和G2类型,请检查数据是否正确!", m_strName.c_str());
            Unlock();
            return -1;
        }
@@ -445,6 +412,7 @@
        pGlass2->setBuddy(pGlass1);
        LOGE("<CBonder-%s>onProcessData,%s和%s已贴合!", m_strName.c_str(),
            pGlass1->getID().c_str(), pGlass2->getID().c_str());
        Unlock();
        return 0;
    }
SourceCode/Bond/Servo/CBonder.h
@@ -16,12 +16,11 @@
        virtual void term();
        virtual void initPins();
        virtual void initSteps();
        virtual void initSlots();
        virtual void onTimer(UINT nTimerid);
        virtual void serialize(CArchive& ar);
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual BOOL glassWillArrive(CGlass* pGlass);
        virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
        virtual int onProcessData(CProcessData* pProcessData);
        virtual int getIndexerOperationModeBaseValue();
SourceCode/Bond/Servo/CEFEM.cpp
@@ -126,15 +126,15 @@
        return 0;
    }
    int CEFEM::SendHome(int seq)
    int CEFEM::robotSendHome(int seq, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmd = {};
        cmd.sequenceNo = static_cast<short>(seq);
        cmd.rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
        return robotCmd(cmd);
        return robotCmd(cmd, onWritedBlock);
    }
    int CEFEM::SendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot)
    int CEFEM::robotSendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmd = {};
        cmd.sequenceNo = static_cast<short>(seq);
@@ -144,10 +144,10 @@
        cmd.getSlotNo = static_cast<short>(fromSlot);
        cmd.putPosition = static_cast<short>(toPos);
        cmd.putSlotNo = static_cast<short>(toSlot);
        return robotCmd(cmd);
        return robotCmd(cmd, onWritedBlock);
    }
    int CEFEM::SendMoveToGet(int seq, int armNo, int pos, int slot)
    int CEFEM::robotSendMoveToGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmd = {};
        cmd.sequenceNo = static_cast<short>(seq);
@@ -156,10 +156,10 @@
        cmd.getPosition = static_cast<short>(pos);
        cmd.getSlotNo = static_cast<short>(slot);
        cmd.subCmd = 1;
        return robotCmd(cmd);
        return robotCmd(cmd, onWritedBlock);
    }
    int CEFEM::SendMoveToPut(int seq, int armNo, int pos, int slot)
    int CEFEM::robotSendMoveToPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmd = {};
        cmd.sequenceNo = static_cast<short>(seq);
@@ -168,10 +168,10 @@
        cmd.putPosition = static_cast<short>(pos);
        cmd.putSlotNo = static_cast<short>(slot);
        cmd.subCmd = 2;
        return robotCmd(cmd);
        return robotCmd(cmd, onWritedBlock);
    }
    int CEFEM::SendGet(int seq, int armNo, int pos, int slot)
    int CEFEM::robotSendGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmd = {};
        cmd.sequenceNo = static_cast<short>(seq);
@@ -179,10 +179,10 @@
        cmd.armNo = static_cast<short>(armNo);
        cmd.getPosition = static_cast<short>(pos);
        cmd.getSlotNo = static_cast<short>(slot);
        return robotCmd(cmd);
        return robotCmd(cmd, onWritedBlock);
    }
    int CEFEM::SendPut(int seq, int armNo, int pos, int slot)
    int CEFEM::robotSendPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmd = {};
        cmd.sequenceNo = static_cast<short>(seq);
@@ -190,10 +190,10 @@
        cmd.armNo = static_cast<short>(armNo);
        cmd.putPosition = static_cast<short>(pos);
        cmd.putSlotNo = static_cast<short>(slot);
        return robotCmd(cmd);
        return robotCmd(cmd, onWritedBlock);
    }
    int CEFEM::SendExchange(int seq, int armNo, int pos, int getSlot, int putSlot)
    int CEFEM::robotSendExchange(int seq, int armNo, int pos, int getSlot, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmd = {};
        cmd.sequenceNo = static_cast<short>(seq);
@@ -203,18 +203,18 @@
        cmd.putPosition = static_cast<short>(pos);
        cmd.getSlotNo = static_cast<short>(getSlot);
        cmd.putSlotNo = static_cast<short>(putSlot);
        return robotCmd(cmd);
        return robotCmd(cmd, onWritedBlock);
    }
    int CEFEM::SendCommandClear(int seq)
    int CEFEM::robotSendCommandClear(int seq, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmd = {};
        cmd.sequenceNo = static_cast<short>(seq);
        cmd.rcmd = static_cast<short>(SERVO::RCMD::Command_Clear);
        return robotCmd(cmd);
        return robotCmd(cmd, onWritedBlock);
    }
    int CEFEM::SendBatchGet(int seq, int getPos, int getSlot)
    int CEFEM::robotSendBatchGet(int seq, int getPos, int getSlot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmd = {};
        cmd.sequenceNo = static_cast<short>(seq);
@@ -222,10 +222,10 @@
        cmd.armNo = ARM_ALL;
        cmd.getPosition = static_cast<short>(getPos);
        cmd.getSlotNo = static_cast<short>(getSlot);
        return robotCmd(cmd);
        return robotCmd(cmd, onWritedBlock);
    }
    int CEFEM::SendBatchPut(int seq, int putPos, int putSlot)
    int CEFEM::robotSendBatchPut(int seq, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmd = {};
        cmd.sequenceNo = static_cast<short>(seq);
@@ -233,10 +233,10 @@
        cmd.armNo = ARM_ALL;
        cmd.putPosition = static_cast<short>(putPos);
        cmd.putSlotNo = static_cast<short>(putSlot);
        return robotCmd(cmd);
        return robotCmd(cmd, onWritedBlock);
    }
    int CEFEM::SendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot)
    int CEFEM::robotSendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmds[2] = {};
@@ -252,10 +252,10 @@
        cmds[1].sequenceNo = static_cast<short>(seq + 1);
        cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
        return robotCmds(cmds, 2);
        return robotCmds(cmds, 2, onWritedBlock);
    }
    int CEFEM::SendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot)
    int CEFEM::robotSendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmds[2] = {};
@@ -271,10 +271,10 @@
        cmds[1].sequenceNo = static_cast<short>(seq + 1);
        cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
        return robotCmds(cmds, 2);
        return robotCmds(cmds, 2, onWritedBlock);
    }
    int CEFEM::SendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot)
    int CEFEM::robotSendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmds[2] = {};
@@ -291,10 +291,10 @@
        cmds[1].sequenceNo = static_cast<short>(seq + 1);
        cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
        return robotCmds(cmds, 2);
        return robotCmds(cmds, 2, onWritedBlock);
    }
    int CEFEM::SendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot)
    int CEFEM::robotSendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmds[2] = {};
@@ -310,10 +310,10 @@
        cmds[1].putPosition = static_cast<short>(putPos);
        cmds[1].putSlotNo = static_cast<short>(putSlot);
        return robotCmds(cmds, 2);
        return robotCmds(cmds, 2, onWritedBlock);
    }
    int CEFEM::SendPutAndHome(int seq, int armNo, int putPos, int putSlot)
    int CEFEM::robotSendPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock/* = nullptr*/)
    {
        SERVO::ROBOT_CMD_PARAM cmds[2] = {};
@@ -328,7 +328,7 @@
        cmds[1].sequenceNo = static_cast<short>(seq + 1);
        cmds[1].rcmd = static_cast<short>(SERVO::RCMD::Robot_home);
        return robotCmds(cmds, 2);
        return robotCmds(cmds, 2, onWritedBlock);
    }
    void CEFEM::init()
@@ -628,6 +628,12 @@
        }
    }
    // å¿…须要实现的虚函数,在此初始化Slot信息
    void CEFEM::initSlots()
    {
    }
    void CEFEM::onTimer(UINT nTimerid)
    {
        CEquipment::onTimer(nTimerid);
@@ -646,16 +652,6 @@
    int CEFEM::recvIntent(CPin* pPin, CIntent* pIntent)
    {
        return __super::recvIntent(pPin, pIntent);
    }
    BOOL CEFEM::glassWillArrive(CGlass* pGlass)
    {
        BOOL bRet = __super::glassWillArrive(pGlass);
        if (!bRet) {
            return FALSE;
        }
        return m_glassList.empty();
    }
    void CEFEM::onReceiveLBData(const char* pszData, size_t size)
SourceCode/Bond/Servo/CEFEM.h
@@ -20,11 +20,11 @@
        virtual void term();
        virtual void initPins();
        virtual void initSteps();
        virtual void initSlots();
        virtual void onTimer(UINT nTimerid);
        virtual void serialize(CArchive& ar);
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual BOOL glassWillArrive(CGlass* pGlass);
        virtual void onReceiveLBData(const char* pszData, size_t size);
        virtual int onReceivedJob(int port, CJobDataS* pJobDataS);
        virtual int onSentOutJob(int port, CJobDataS* pJobDataS);
@@ -41,21 +41,21 @@
        int robotCmds(ROBOT_CMD_PARAM* robotCmdParam, unsigned int count, ONWRITED onWritedBlock = nullptr);
        // å¿«æ·å°è£…
        int SendHome(int seq);
        int SendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot);
        int SendMoveToGet(int seq, int armNo, int pos, int slot);
        int SendMoveToPut(int seq, int armNo, int pos, int slot);
        int SendGet(int seq, int armNo, int pos, int slot);
        int SendPut(int seq, int armNo, int pos, int slot);
        int SendExchange(int seq, int armNo, int pos, int getSlot, int putSlot);
        int SendCommandClear(int seq);
        int SendBatchGet(int seq, int getPos, int getSlot);
        int SendBatchPut(int seq, int putPos, int putSlot);
        int SendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot);
        int SendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot);
        int SendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot);
        int SendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot);
        int SendPutAndHome(int seq, int armNo, int putPos, int putSlot);
        int robotSendHome(int seq, ONWRITED onWritedBlock = nullptr);
        int robotSendTransfer(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock = nullptr);
        int robotSendMoveToGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
        int robotSendMoveToPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
        int robotSendGet(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
        int robotSendPut(int seq, int armNo, int pos, int slot, ONWRITED onWritedBlock = nullptr);
        int robotSendExchange(int seq, int armNo, int pos, int getSlot, int putSlot, ONWRITED onWritedBlock = nullptr);
        int robotSendCommandClear(int seq, ONWRITED onWritedBlock = nullptr);
        int robotSendBatchGet(int seq, int getPos, int getSlot, ONWRITED onWritedBlock = nullptr);
        int robotSendBatchPut(int seq, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
        int robotSendMoveToGetAndHome(int seq, int armNo, int getPos, int getSlot, ONWRITED onWritedBlock = nullptr);
        int robotSendMoveToPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
        int robotSendTransferAndHome(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot, ONWRITED onWritedBlock = nullptr);
        int robotSendGetAndPut(int seq, int armNo, int getPos, int getSlot, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
        int robotSendPutAndHome(int seq, int armNo, int putPos, int putSlot, ONWRITED onWritedBlock = nullptr);
    private:
        CLoadPort* m_pPort[4];
SourceCode/Bond/Servo/CEqAlarmStep.h
@@ -7,7 +7,7 @@
    {
    public:
        CEqAlarmStep();
        ~CEqAlarmStep();
        virtual ~CEqAlarmStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CEqCassetteCtrlCmdStep.h
@@ -8,7 +8,7 @@
    {
    public:
        CEqCassetteCtrlCmdStep();
        ~CEqCassetteCtrlCmdStep();
        virtual ~CEqCassetteCtrlCmdStep();
    public:
        void setCtrlCmdDev(int nDev);
SourceCode/Bond/Servo/CEqCassetteTransferStateStep.h
@@ -7,7 +7,7 @@
    {
    public:
        CEqCassetteTransferStateStep();
        ~CEqCassetteTransferStateStep();
        virtual ~CEqCassetteTransferStateStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CEqCimMessageClearStep.h
@@ -7,7 +7,7 @@
    {
    public:
        CEqCimMessageClearStep();
        ~CEqCimMessageClearStep();
        virtual ~CEqCimMessageClearStep();
    public:
        void setClearCimMessageDev(int nDev);
SourceCode/Bond/Servo/CEqCimMessageCmdStep.h
@@ -7,7 +7,7 @@
    {
    public:
        CEqCimMessageCmdStep();
        ~CEqCimMessageCmdStep();
        virtual ~CEqCimMessageCmdStep();
    public:
        void setCimMessageDev(int nDev);
SourceCode/Bond/Servo/CEqCimModeChangeStep.h
@@ -7,7 +7,7 @@
    {
    public:
        CEqCimModeChangeStep();
        ~CEqCimModeChangeStep();
        virtual ~CEqCimModeChangeStep();
    public:
        void setCimModeDev(int nDev);
SourceCode/Bond/Servo/CEqCurrentRecipeChangeStep.h
@@ -7,7 +7,7 @@
    {
    public:
        CEqCurrentRecipeChangeStep();
        ~CEqCurrentRecipeChangeStep();
        virtual ~CEqCurrentRecipeChangeStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CEqDateTimeSetCmdStep.h
@@ -7,7 +7,7 @@
    {
    public:
        CEqDateTimeSetCmdStep();
        ~CEqDateTimeSetCmdStep();
        virtual ~CEqDateTimeSetCmdStep();
    public:
        void setDateTimeDev(int nDev);
SourceCode/Bond/Servo/CEqJobEventStep.h
@@ -8,7 +8,7 @@
    {
    public:
        CEqJobEventStep();
        ~CEqJobEventStep();
        virtual ~CEqJobEventStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CEqModeChangeStep.h
@@ -7,7 +7,7 @@
    {
    public:
        CEqModeChangeStep();
        ~CEqModeChangeStep();
        virtual ~CEqModeChangeStep();
    public:
        void setEqModeDev(int nDev);
SourceCode/Bond/Servo/CEqModeStep.h
@@ -7,7 +7,7 @@
    {
    public:
        CEqModeStep();
        ~CEqModeStep();
        virtual ~CEqModeStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CEqPortChangeStep.h
@@ -6,7 +6,7 @@
    {
    public:
        CEqPortChangeStep();
        ~CEqPortChangeStep();
        virtual ~CEqPortChangeStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CEqProcessStep.h
@@ -8,7 +8,7 @@
    {
    public:
        CEqProcessStep();
        ~CEqProcessStep();
        virtual ~CEqProcessStep();
    public:
        void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CEqReadIntStep.h
@@ -11,7 +11,7 @@
    public:
        CEqReadIntStep();
        CEqReadIntStep(int dataType, int dev);
        ~CEqReadIntStep();
        virtual ~CEqReadIntStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CEqReadStep.h
@@ -18,7 +18,7 @@
    public:
        CEqReadStep();
        CEqReadStep(int dev, size_t readSize, ONREAD onReadBlock);
        ~CEqReadStep();
        virtual ~CEqReadStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CEqStatusStep.h
@@ -10,7 +10,7 @@
    {
    public:
        CEqStatusStep();
        ~CEqStatusStep();
        virtual ~CEqStatusStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CEqVCREnableStep.h
@@ -7,7 +7,7 @@
    {
    public:
        CEqVCREnableStep();
        ~CEqVCREnableStep();
        virtual ~CEqVCREnableStep();
    public:
        void setEqVCRModeDev(int nDev);
SourceCode/Bond/Servo/CEqVcrEventStep.h
@@ -8,7 +8,7 @@
    {
    public:
        CEqVcrEventStep();
        ~CEqVcrEventStep();
        virtual ~CEqVcrEventStep();
    public:
        virtual void getAttributeVector(CAttributeVector& attrubutes);
SourceCode/Bond/Servo/CEqWriteStep.h
@@ -13,7 +13,7 @@
    {
    public:
        CEqWriteStep();
        ~CEqWriteStep();
        virtual ~CEqWriteStep();
    public:
        void setDataDev(int nDev);
SourceCode/Bond/Servo/CEquipment.cpp
@@ -27,7 +27,7 @@
    CEquipment::CEquipment() : m_nID(0), m_strName(""), m_strDescription(""), m_station(0, 255)
    {
        m_listener = { nullptr, nullptr, nullptr, nullptr, nullptr };
        m_listener = { };
        m_alive = { FALSE, 0, FALSE };
        m_bCimState = FALSE;
        m_bUpstreamInline = FALSE;
@@ -43,10 +43,13 @@
    CEquipment::~CEquipment()
    {
        for (auto item : m_glassList) {
            item->release();
        for (int i = 0; i < SLOT_MAX; i++) {
            CContext* pContext = m_slot[i].getContext();
            if (pContext != nullptr) {
                pContext->release();
                m_slot[i].setContext(nullptr);
        }
        m_glassList.clear();
        }
        for (auto item : m_mapStep) {
            delete item.second;
@@ -68,11 +71,7 @@
    void CEquipment::setListener(EquipmentListener listener)
    {
        m_listener.onAlive = listener.onAlive;
        m_listener.onCimStateChanged = listener.onCimStateChanged;
        m_listener.onAlarm = listener.onAlarm;
        m_listener.onDataChanged = listener.onDataChanged;
        m_listener.onVcrEventReport = listener.onVcrEventReport;
        m_listener = listener;
    }
    void CEquipment::setCcLink(CCCLinkIEControl* pCcLink)
@@ -149,6 +148,7 @@
    {
        initPins();
        initSteps();
        initSlots();
        for (auto item : m_mapStep) {
            item.second->init();
        }
@@ -251,9 +251,19 @@
                std::to_string((int)item->getType()).c_str(), "", weight++));
        }
        for (auto item : m_glassList) {
            attrubutes.addAttribute(new CAttribute("Glass",
                item->getID().c_str(), "", weight++));
        for (int i = 0; i < SLOT_MAX; i++) {
            if (!m_slot[i].isEnable()) continue;
            CGlass* pGlass = (CGlass*)m_slot[i].getContext();
            if (pGlass == nullptr) {
                attrubutes.addAttribute(new CAttribute(m_slot[i].getName().c_str(),
                    "", "", weight++));
            }
            else {
                attrubutes.addAttribute(new CAttribute(m_slot[i].getName().c_str(),
                    pGlass->getID().c_str(), "", weight++));
            }
        }
    }
@@ -305,24 +315,26 @@
    {
        if (ar.IsStoring()) {
            Lock();
            int count = (int)m_glassList.size();
            ar << count;
            for (auto item : m_glassList) {
                item->serialize(ar);
            for (int i = 0; i < SLOT_MAX; i++) {
                m_slot[i].serialize(ar);
                if (m_slot[i].getContext() != nullptr) {
                    ((CGlass*)m_slot[i].getContext())->serialize(ar);
                }
            }
            Unlock();
        }
        else {
            // addGlassToList前不需要上锁,因其内部有锁
            int count;
            ar >> count;
            for (int i = 0; i < count; i++) {
            for (int i = 0; i < SLOT_MAX; i++) {
                m_slot[i].serialize(ar);
                if (m_slot[i].getContext() != nullptr) {
                CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass();
                pGlass->serialize(ar);
                addGlassToList(pGlass);
                    m_slot[i].setContext(pGlass);
                }
            }
            
            // æ¢³ç†å„玻璃之间的绑定关系
            /*
            Lock();
            std::list<CGlass*> list = m_glassList;
            for (auto item : list) {
@@ -337,6 +349,7 @@
                }
            }
            Unlock();
            */
        }
    }
@@ -690,175 +703,10 @@
        // æµ‹è¯•
        if (code == FLOW_TEST) {
            AfxMessageBox(pIntent->getMsg());
            return FLOW_ACCEPT;
        }
        // ä¿¡å·
        if (code == FLOW_SIGNAL) {
            return FLOW_ACCEPT;
        }
        // æ•°æ®
        if (code == FLOW_SIGNAL) {
            return FLOW_ACCEPT;
        }
        // ç‰©æ–™
        if (code == FLOW_MOVE_MATERIAL) {
            CGlass* pGlass = (CGlass*)pIntent->getContext();
            ASSERT(pGlass);
            if (!glassWillArrive(pGlass)) {
                return FLOW_REJECT;
            }
            return glassArrived(pGlass);
        }
        return FLOW_ACCEPT;
    }
    int CEquipment::outputGlass(int port)
    {
        CPin* pOutPin = nullptr;
        if (port == 0) {
            pOutPin = getPin("Out");
            if (pOutPin == nullptr) {
                pOutPin = getPin("Out1");
            }
        }
        else if (port == 1) {
            pOutPin = getPin("Out2");
        }
        if (pOutPin == nullptr) {
            return -1;
        }
        // æ¨¡æ‹Ÿå–出第一张Panel,传送到下一环节
        ULONGLONG time = CToolUnits::getTimestamp();
        Lock();
        if (m_glassList.empty()) {
            Unlock();
            return -2;
        }
        CGlass* pContext = m_glassList.front();
        pContext->addRef();
        CIntent intent(FLOW_MOVE_MATERIAL, "", pContext);
        int nRet = pOutPin->sendIntent(&intent);
        if (nRet == FLOW_REJECT) {
            LOGE("<CEquipment>对方拒绝接收Intent.");
        }
        else if (nRet == FLOW_ACCEPT) {
            CPath* pPath = pContext->getPathWithSiteID(m_nID);
            if (pPath != nullptr) {
                pPath->setOutTime(time);
            }
            m_glassList.pop_front();
            pContext->release();        // æ·»åŠ åˆ°åˆ—é˜Ÿæ—¶addRef, å–出时release
            if (m_listener.onDataChanged != nullptr) {
                m_listener.onDataChanged(this, 0);
            }
        }
        pContext->release();
        Unlock();
        return 0;
    }
    BOOL CEquipment::glassWillArrive(CGlass* pGlass)
    {
        return TRUE;
    }
    int CEquipment::glassArrived(CGlass* pGlass)
    {
        Lock();
        pGlass->addPath(m_nID);
        pGlass->addRef();
        m_glassList.push_back(pGlass);
        Unlock();
        if (m_listener.onDataChanged != nullptr) {
            m_listener.onDataChanged(this, 0);
        }
        return FLOW_ACCEPT;
    }
    void CEquipment::addGlassToList(CGlass* pGlass)
    {
        ASSERT(pGlass);
        Lock();
        pGlass->addRef();
        m_glassList.push_back(pGlass);
        Unlock();
        if (m_listener.onDataChanged != nullptr) {
            m_listener.onDataChanged(this, 0);
        }
    }
    CGlass* CEquipment::getGlassFromList(const char* pszId)
    {
        CGlass* pGlass = nullptr;
        Lock();
        for (auto item : m_glassList) {
            if (item->getID().compare(pszId) == 0) {
                pGlass = item;
                break;
            }
        }
        Unlock();
        return pGlass;
    }
    BOOL CEquipment::removeClass(CGlass* pGlass)
    {
        Lock();
        bool bExist = std::find(m_glassList.begin(), m_glassList.end(), pGlass) != m_glassList.end();
        if (bExist) {
            pGlass->addPath(EQ_ID_OPERATOR_REMOVE);
            pGlass->release();
            m_glassList.remove(pGlass);
        }
        Unlock();
        if (bExist && m_listener.onDataChanged != nullptr) {
            m_listener.onDataChanged(this, 0);
        }
        return bExist;
    }
    void CEquipment::getGlassList(std::list<CGlass*>& list)
    {
        Lock();
        for (auto item : m_glassList) {
            item->addRef();
            list.push_back(item);
        }
        Unlock();
    }
    CGlass* CEquipment::getFrontGlass()
    {
        CGlass* pGlass = nullptr;
        Lock();
        if (!m_glassList.empty()) {
            pGlass = m_glassList.front();
        }
        Unlock();
        return pGlass;
    }
    int CEquipment::fetchedOutJob(CJobDataB* pJobDataB)
@@ -869,16 +717,12 @@
        // æ‰¾åˆ°æŒ‡å®šçš„glass id, 
        Lock();
        if (m_glassList.empty()) {
            Unlock();
            return -2;
        }
        CGlass* pContext = nullptr;
        for (auto iter = m_glassList.begin(); iter != m_glassList.end(); iter++) {
            if ((*iter)->getID().compare(pJobDataB->getGlassId()) == 0) {
                pContext = (*iter);
                m_glassList.erase(iter);
        for (int i = 0; i < SLOT_MAX; i++) {
            CGlass* pGlass = (CGlass*)m_slot[i].getContext();
            if (pGlass != nullptr && compareJobDataB(pJobDataB, pGlass->getJobDataB())) {
                pContext = pGlass;
                m_slot[i].setContext(nullptr);
                break;
            }
        }
@@ -890,10 +734,11 @@
        // å¦‚果此玻璃已经贴合,贴合的玻璃也要从列表中移除
        CGlass* pBuddy = pContext->getBuddy();
        if (pBuddy != nullptr) {
            for (auto iter = m_glassList.begin(); iter != m_glassList.end(); iter++) {
                if ((*iter)->getID().compare(pBuddy->getID()) == 0) {
                    (*iter)->release();
                    m_glassList.erase(iter);
            for (int i = 0; i < SLOT_MAX; i++) {
                CGlass* pGlass = (CGlass*)m_slot[i].getContext();
                if (pGlass != nullptr && compareJobDataB(pBuddy->getJobDataB(), pGlass->getJobDataB())) {
                    pContext->release();
                    m_slot[i].setContext(nullptr);
                    break;
                }
            }
@@ -905,13 +750,13 @@
        Unlock();
        if (m_listener.onDataChanged != nullptr) {
            m_listener.onDataChanged(this, 0);
            m_listener.onDataChanged(this, EDCC_FETCHOUT_JOB);
        }
        return 0;
    }
    int CEquipment::storedJob(CJobDataB* pJobDataB)
    int CEquipment::storedJob(CJobDataB* pJobDataB, short& putSlot)
    {
        if (m_pArm == nullptr) {
            return -1;
@@ -926,13 +771,13 @@
        ASSERT(pGlass);
        Lock();
        pGlass->addPath(m_nID);
        pGlass->addRef();                    // åŠ å…¥list,addRef
        m_glassList.push_back(pGlass);
        m_slot[putSlot - 1].setContext(pGlass);
        pGlass->release();                // tempFetchOut需要调用一次release
        Unlock();
        // å¦‚果此玻璃已经贴合,贴合的玻璃也要从加入到列表中
        /*
        CGlass* pBuddy = pGlass->getBuddy();
        if (pBuddy != nullptr) {
            Lock();
@@ -941,18 +786,24 @@
            m_glassList.push_back(pBuddy);
            Unlock();
        }
        */
        if (m_listener.onDataChanged != nullptr) {
            m_listener.onDataChanged(this, 0);
            m_listener.onDataChanged(this, EDCC_STORED_JOB);
        }
        return 0;
    }
    BOOL CEquipment::isGlassListEmpty()
    BOOL CEquipment::hasGlass()
    {
        return m_glassList.empty();
        for (int i = 0; i < SLOT_MAX; i++) {
            if (m_slot[i].isEnable() && !m_slot[i].isEmpty()) {
                return TRUE;
            }
        }
        return FALSE;
    }
    bool CEquipment::isAlarmStep(SERVO::CStep* pStep)
@@ -1099,7 +950,7 @@
            return -1;
        }
        unsigned short operationMode = (unsigned short)(mode + getIndexerOperationModeBaseValue());
        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);
@@ -1168,6 +1019,93 @@
            return 0;
            });
        return 0;
    }
    CSlot* CEquipment::getAvailableSlot()
    {
        for (int i = 0; i < SLOT_MAX; i++) {
            if (!m_slot[i].isEnable()) continue;
            if (m_slot[i].isLock()) continue;
            if (!m_slot[i].isEmpty()) continue;
            return &m_slot[i];
        }
        return nullptr;
    }
    CSlot* CEquipment::getAvailableSlotForGlass(MaterialsType type)
    {
        for (int i = 0; i < SLOT_MAX; i++) {
            if (!m_slot[i].isEnable()) continue;
            if (m_slot[i].isLock()) continue;
            if (!m_slot[i].isEmpty()) continue;
            MaterialsType slotType = m_slot[i].getType();
            if (type == MaterialsType::G1 && slotType == MaterialsType::G2) continue;
            if (type == MaterialsType::G2 && slotType == MaterialsType::G1) continue;
            return &m_slot[i];
        }
        return nullptr;
    }
    CSlot* CEquipment::getNonEmptySlot(MaterialsType putSlotType)
    {
        for (int i = 0; i < SLOT_MAX; i++) {
            if (!m_slot[i].isEnable()) continue;
            if (m_slot[i].isLock()) continue;
            CGlass* pGlass = (CGlass*)m_slot[i].getContext();
            if (pGlass == nullptr) continue;
            MaterialsType glassType = pGlass->getType();
            if (glassType == MaterialsType::G1 && putSlotType == MaterialsType::G2) continue;
            if (glassType == MaterialsType::G2 && putSlotType == MaterialsType::G1) continue;
            return &m_slot[i];
        }
        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::getAnyGlass()
    {
        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;
            return pGlass;
        }
        return nullptr;
    }
    BOOL CEquipment::canPlaceGlassInSlot(const short slotIndex)
    {
        if (slotIndex >= SLOT_MAX) return FALSE;
        if (!m_slot[slotIndex].isEnable()) return FALSE;
        if (m_slot[slotIndex].getContext() != nullptr) return FALSE;
        return TRUE;
    }
    short CEquipment::decodeRecipeListReport(const char* pszData, size_t size)
@@ -1299,10 +1237,14 @@
        return index;
    }
    int CEquipment::onPreFetchedOutJob(int port, CJobDataB* pJobDataB)
    BOOL CEquipment::onPreFetchedOutJob(int port, CJobDataB* pJobDataB)
    {
        LOGI("<CEquipment-%s>onPreFetchedOutJob:port:%d|GlassId:%s",
            m_strName.c_str(), port, pJobDataB->getGlassId().c_str());
        if (m_listener.onPreFethedOutJob != nullptr) {
            return m_listener.onPreFethedOutJob(this, pJobDataB);
        }
        return TRUE;
    }
@@ -1385,10 +1327,39 @@
        return 0;
    }
    int CEquipment::onPreStoredJob(int port, CJobDataB* pJobDataB)
    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(),
                pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
            return FALSE;
        }
        // å¦‚果没有可用位置,报错
        Lock();
        CSlot* pSlot = getAvailableSlotForGlass((MaterialsType)pJobDataS->getMaterialsType());
        if (pSlot == nullptr) {
            Unlock();
            LOGE("<CFliper-%s>onPreFetchedOutJob,找不到匹配的Slot,不能进料,请注意风险!", m_strName.c_str());
            return FALSE;
        }
        Unlock();
        if (m_listener.onPreStoredJob != nullptr) {
            if (!m_listener.onPreStoredJob(this, pJobDataB, putSlot)) {
                return FALSE;
            }
            if(!canPlaceGlassInSlot(putSlot - 1)) {
                return FALSE;
            }
        }
        return TRUE;
    }
@@ -1397,10 +1368,11 @@
        LOGI("<CEquipment-%s>onStore:port:%d|GlassId:%s",
            m_strName.c_str(), port, pJobDataB->getGlassId().c_str());
        BOOL bCheck = onPreStoredJob(port, pJobDataB);
        short putSlot = 0;
        BOOL bCheck = onPreStoredJob(port, pJobDataB, putSlot);
        if (bCheck) {
            addJobDataB(pJobDataB);
            return storedJob(pJobDataB);
            return storedJob(pJobDataB, putSlot);
        }
        // æ•°æ®å¼‚常,处理或显示
@@ -1509,4 +1481,17 @@
        return nullptr;
    }
    BOOL CEquipment::compareJobDataB(CJobDataB* pJobDataB1, CJobDataB* pJobDataB2)
    {
        ASSERT(pJobDataB1);
        ASSERT(pJobDataB2);
        if (pJobDataB1->getCassetteSequenceNo() != pJobDataB2->getCassetteSequenceNo())
            return FALSE;
        if (pJobDataB1->getJobSequenceNo() != pJobDataB2->getJobSequenceNo())
            return FALSE;
        return TRUE;
    }
}
SourceCode/Bond/Servo/CEquipment.h
@@ -1,5 +1,6 @@
#pragma once
#include "Log.h"
#include "ServoCommo.h"
#include "CCLinkIEControl.h"
#include "CSample.h"
#include "CPin.h"
@@ -33,18 +34,18 @@
#include "CJobDataS.h"
#include "CProcessData.h"
#include "CPortStatusReport.h"
#include "CSlot.h"
namespace SERVO {
#define BLOCK_BUFFER_MAX            1024
#define ALIVE_TIMEOUT                15
#define VCR_MAX                        1
#define ARM_ALL                        99
#define SLOT_MAX        12
    typedef std::function<void(void* pEiuipment, BOOL bAlive)> ONALIVE;
    typedef std::function<void(void* pEiuipment, int code)> ONDATACHANGED;
    typedef std::function<void(void* pEiuipment, int state, int alarmId, int unitId, int level)> ONALARM;
    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 struct _EquipmentListener
    {
        ONALIVE                onAlive;
@@ -52,80 +53,16 @@
        ONALARM                onAlarm;
        ONDATACHANGED        onDataChanged;
        ONVCREVENTREPORT    onVcrEventReport;
        ONPREFETCHEDOUTJOB    onPreFethedOutJob;
        ONPRESTOREDJOB        onPreStoredJob;
    } EquipmentListener;
    // Memory Block ç»“构体定义
    typedef struct _MemoryBlock {
        unsigned int type;
        unsigned int start;
        unsigned int end;
        unsigned int size;
        char buffer[BLOCK_BUFFER_MAX];
    } MemoryBlock;
    // ALIVE
    typedef struct _ALIVE {
        BOOL flag;
        int count;
        BOOL alive;
    } ALIVE;
    enum DISPATCHING_MODE {
        EAS = 1,
        Local = 2
    };
    enum IDNEXER_OPERATION_MODE {
        Normal = 1,
        Clear_Out = 2,
        Cold_Run = 2,
        Start = 10,
        Stop = 11,
        Pause = 12,
        Resume = 13,
        Abort = 14,
        Cancel = 15,
    };
    enum RCMD {
        Robot_home = 1,
        Transfer,
        Move,
        Get,
        Put,
        One_Action_Exchange,
        Two_Action_Exchange,
        Command_Clear,
        Batch_get,
        Batch_put
    };
    enum VCR_Reply_Code {
        OK = 1,
        NG,
        Job_Data_Request,
        VCR_Mismatch
    };
    // Robot cmd param
#define ROBOT_CMD_PARAM_SIZE        16            /* é˜²æ­¢ä»¥åŽä¿®æ”¹ROBOT_CMD_PARAM为不是4的整数倍 */
    typedef struct _ROBOT_CMD_PARAM {
        short sequenceNo;
        short rcmd;
        short armNo;
        short getPosition;
        short putPosition;
        short getSlotNo;
        short putSlotNo;
        short subCmd;
    } ROBOT_CMD_PARAM;
    class CEquipment
    {
    public:
        CEquipment();
        virtual ~CEquipment();
    public:
        virtual const char* getClassName() = 0;
@@ -158,6 +95,7 @@
        virtual void term();
        virtual void initPins() = 0;
        virtual void initSteps();
        virtual void initSlots() = 0;
        virtual void onTimer(UINT nTimerid);
        virtual void serialize(CArchive& ar);
        virtual void onReceiveLBData(const char* pszData, size_t size);
@@ -167,23 +105,16 @@
        std::vector<CPin*>& CEquipment::getInputPins();
        std::vector<CPin*>& CEquipment::getOutputPins();
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual BOOL glassWillArrive(CGlass* pGlass);
        virtual int outputGlass(int port);
        virtual int glassArrived(CGlass* pGlass);
        virtual int fetchedOutJob(CJobDataB* pJobDataB);
        virtual int storedJob(CJobDataB* pJobDataB);
        virtual int storedJob(CJobDataB* pJobDataB, short& putSlot);
        virtual int onReceivedJob(int port, CJobDataS* pJobDataS);
        virtual int onSentOutJob(int port, CJobDataS* pJobDataS);
        virtual BOOL onPreFetchedOutJob(int port, CJobDataB* pJobDataB);
        virtual int onFetchedOutJob(int port, CJobDataB* pJobDataB);
        virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
        virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB, short& putSlot);
        virtual int onStoredJob(int port, CJobDataB* pJobDataB);
        virtual int onProcessData(CProcessData* pProcessData);
        virtual int getIndexerOperationModeBaseValue();
        void getGlassList(std::list<CGlass*>& list);
        CGlass* getGlassFromList(const char* pszId);
        CGlass* getFrontGlass();
        BOOL removeClass(CGlass* pGlass);
        bool isAlarmStep(SERVO::CStep* pStep);
        bool isVcrEventStep(SERVO::CStep* pStep);
        bool isCassetteTransferStateStep(SERVO::CStep* pStep);
@@ -214,8 +145,27 @@
        // unitNo: 0:local; Others:unit No
        int recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo);
    public:
        BOOL isGlassListEmpty();
        // èŽ·å–ä¸€ä¸ªå¯ç”¨çš„æ§½ä½
        CSlot* getAvailableSlot();
        // èŽ·å–ä¸€ä¸ªæŒ‡å®šç‰©æ–™ç±»åž‹(G1,G2,G1&G2)的空槽位
        CSlot* getAvailableSlotForGlass(MaterialsType type);
        // èŽ·å–ä¸€ä¸ªæŒ‡å®šç‰©æ–™ç±»åž‹(G1,G2,G1&G2)的非空槽位
        CSlot* getNonEmptySlot(MaterialsType type);
        // èŽ·å–çŽ»ç’ƒç‰©æ–™
        CGlass* getGlassFromSlot(int slotNo);
        CGlass* getAnyGlass();
        // éªŒè¯çŽ»ç’ƒå’Œæ§½æ˜¯å¦åŒ¹é…
        BOOL ValidateGlassSlotMatch();
        // æ˜¯å¦æœ‰çŽ»ç’ƒ
        BOOL hasGlass();
        // æŒ‡å®šæ§½ä½æ˜¯å¦å¯ä»¥æ”¾ç½®çŽ»ç’ƒ
        BOOL canPlaceGlassInSlot(const short slotIndex);
    // ä»¥ä¸‹ä¸ºä»ŽCC-Link读取到的Bit标志位检测函数
@@ -233,7 +183,6 @@
        inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
        BOOL isBitOn(const char* pszData, size_t size, int index);
        inline BOOL equalBool(BOOL b1, BOOL b2);
        void addGlassToList(CGlass* pGlass);
        short decodeRecipeListReport(const char* pszData, size_t size);
        short decodeRecipeParameterReport(const char* pszData, size_t size);
        int decodeProcessDataReport(CStep* pStep, const char* pszData, size_t size);
@@ -248,6 +197,7 @@
        int addJobDataS(CJobDataS* pJobDataS);
        int removeJobDataS(int nCassetteSequenceNo, int nJobSequenceNo);
        CJobDataS* getJobDataS(int nCassetteSequenceNo, int nJobSequenceNo);
        BOOL compareJobDataB(CJobDataB* pJobDataB1, CJobDataB* pJobDataB2);
    protected:
        EquipmentListener m_listener;
@@ -260,7 +210,6 @@
        MemoryBlock m_blockWriteBit;
        std::vector<CPin*> m_inputPins;
        std::vector<CPin*> m_outputPins;
        std::list<CGlass*> m_glassList;
        // ä»¥ä¸‹ä¸ºä»ŽCC-Link读取到的Bit标志位
@@ -278,6 +227,7 @@
        std::map<unsigned int, CStep*> m_mapStep;
        int m_nBaseAlarmId;
        CRecipesManager m_recipesManager;
        CSlot m_slot[SLOT_MAX];
    private:
        CEquipment* m_pArm;
SourceCode/Bond/Servo/CEquipmentPage2.cpp
@@ -80,16 +80,14 @@
    ASSERT(m_pEquipment);
    std::list<SERVO::CGlass*> list;
    m_pEquipment->getGlassList(list);
    for (auto item : list) {
        item->addRef();
        item->release();        // é‡Šæ”¾list中的引用
    for (int i = 0; i < SLOT_MAX; i++) {
        SERVO::CGlass* pGlass = m_pEquipment->getGlassFromSlot(i+1);
        pGlass->addRef();
        SERVO::CGlass* pBuddy = item->getBuddy();
        SERVO::CGlass* pBuddy = pGlass->getBuddy();
        int index = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), _T(""));
        m_listCtrl.SetItemData(index, (DWORD_PTR)item);
        m_listCtrl.SetItemText(index, 1, item->getID().c_str());
        m_listCtrl.SetItemData(index, (DWORD_PTR)pGlass);
        m_listCtrl.SetItemText(index, 1, pGlass->getID().c_str());
        if (pBuddy != nullptr) {
            m_listCtrl.SetItemText(index, 2, pBuddy->getID().c_str());
        }
@@ -172,6 +170,7 @@
void CEquipmentPage2::OnBnClickedButtonRemove()
{
    /*
    int index = GetSelectedItemIndex();
    if (index >= 0) {
        SERVO::CGlass* pGlass = (SERVO::CGlass*)m_listCtrl.GetItemData(index);
@@ -182,4 +181,5 @@
            m_listCtrl.DeleteItem(index);
        }
    }
    */
}
SourceCode/Bond/Servo/CFliper.cpp
@@ -38,6 +38,16 @@
        addPin(SERVO::PinType::OUTPUT, _T("Out"));
    }
    // å¿…须要实现的虚函数,在此初始化Slot信息
    void CFliper::initSlots()
    {
        m_slot[0].enable();
        m_slot[0].setPosition(m_nID);
        m_slot[0].setNo(1);
        m_slot[0].setName("Slot 1(G2)");
        m_slot[0].setType(MaterialsType::G2);
    }
    void CFliper::onTimer(UINT nTimerid)
    {
        CEquipment::onTimer(nTimerid);
@@ -56,40 +66,5 @@
    int CFliper::recvIntent(CPin* pPin, CIntent* pIntent)
    {
        return __super::recvIntent(pPin, pIntent);
    }
    BOOL CFliper::glassWillArrive(CGlass* pGlass)
    {
        BOOL bRet = __super::glassWillArrive(pGlass);
        if (!bRet) {
            return FALSE;
        }
        return m_glassList.empty();
    }
    BOOL CFliper::onPreStoredJob(int port, CJobDataB* pJobDataB)
    {
        CJobDataS* pJobDataS = getJobDataS(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
        if (pJobDataS == nullptr) {
            LOGE("<CFliper-%s>onPreFetchedOutJob,找不到对应的JobDataS(CassetteSequenceNo:%d, JobSequenceNo:%d), æ³¨æ„æŽ’查风险!", m_strName.c_str(),
                pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
            return FALSE;
        }
        // å½“前不能有任何玻璃,且当前准备进的片是G2
        Lock();
        if (!m_glassList.empty()) {
            Unlock();
            LOGE("<CFliper-%s>onPreFetchedOutJob,当前机器或单元存在玻璃片,不能进料,请注意风险!", m_strName.c_str());
            return FALSE;
        }
        if (pJobDataS->getMaterialsType() != (int)MaterialsType::G2) {
            LOGE("<CFliper-%s>onPreFetchedOutJob,当前机器或单元只能进G2玻璃片,请注意风险!", m_strName.c_str());
            return FALSE;
        }
        return TRUE;
    }
}
SourceCode/Bond/Servo/CFliper.h
@@ -15,12 +15,11 @@
        virtual void init();
        virtual void term();
        virtual void initPins();
        virtual void initSlots();
        virtual void onTimer(UINT nTimerid);
        virtual void serialize(CArchive& ar);
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual BOOL glassWillArrive(CGlass* pGlass);
        virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
    };
}
SourceCode/Bond/Servo/CGlassPool.h
@@ -9,7 +9,7 @@
    {
    public:
        CGlassPool();
        ~CGlassPool();
        virtual ~CGlassPool();
    public:
        void initPool();
SourceCode/Bond/Servo/CJobDataA.cpp
@@ -6,7 +6,7 @@
namespace SERVO {
    CJobDataA::CJobDataA()
    {
        m_pOwner = nullptr;
    }
    CJobDataA::~CJobDataA()
@@ -14,6 +14,16 @@
    }
    void* CJobDataA::getOwner()
    {
        return m_pOwner;
    }
    void CJobDataA::setOwner(void* pOwner)
    {
        m_pOwner = pOwner;
    }
    short CJobDataA::getPortNo()
    {
        return m_nPortNo;
SourceCode/Bond/Servo/CJobDataA.h
@@ -8,9 +8,11 @@
    {
    public:
        CJobDataA();
        ~CJobDataA();
        virtual ~CJobDataA();
    public:
        void* getOwner();
        void setOwner(void* pOwner);
        short getPortNo();
        std::string& getCarrierId();
        std::string& getPruductId();
@@ -23,6 +25,7 @@
        int unserialize(const char* pszBuffer, int nBufferSize);
    private:
        void* m_pOwner;
        short m_nPortNo;
        std::string m_strCarrierId;
        std::string m_pruductId;
SourceCode/Bond/Servo/CJobDataB.cpp
@@ -8,6 +8,7 @@
    {
        m_nCassetteSequenceNo = 0;
        m_nJobSequenceNo = 0;
        m_pOwner = nullptr;
    }
    CJobDataB::CJobDataB(CJobDataB&& other) noexcept
@@ -25,6 +26,17 @@
        m_nCassetteSequenceNo = pScr->m_nCassetteSequenceNo;
        m_nJobSequenceNo = pScr->m_nJobSequenceNo;
        m_strGlassId = pScr->m_strGlassId;
        m_pOwner = pScr->m_pOwner;
    }
    void* CJobDataB::getOwner()
    {
        return m_pOwner;
    }
    void CJobDataB::setOwner(void* pOwner)
    {
        m_pOwner = pOwner;
    }
    int CJobDataB::getCassetteSequenceNo()
SourceCode/Bond/Servo/CJobDataB.h
@@ -8,9 +8,11 @@
    public:
        CJobDataB();
        CJobDataB::CJobDataB(CJobDataB&& other) noexcept;
        ~CJobDataB();
        virtual ~CJobDataB();
    public:
        void* getOwner();
        void setOwner(void* pOwner);
        void copy(CJobDataB* pScr);
        int getCassetteSequenceNo();
        void setCassetteSequenceNo(int no);
@@ -22,6 +24,7 @@
        int unserialize(const char* pszBuffer, int nBufferSize);
    private:
        void* m_pOwner;
        int m_nCassetteSequenceNo;
        int m_nJobSequenceNo;
        std::string m_strGlassId;
SourceCode/Bond/Servo/CJobDataC.cpp
@@ -6,6 +6,7 @@
    CJobDataC::CJobDataC()
    {
        m_nCassetteSequenceNo = 0;
        m_pOwner = nullptr;
    }
    CJobDataC::~CJobDataC()
@@ -13,6 +14,16 @@
        m_nCassetteProcessFlag = 0;
    }
    void* CJobDataC::getOwner()
    {
        return m_pOwner;
    }
    void CJobDataC::setOwner(void* pOwner)
    {
        m_pOwner = pOwner;
    }
    int CJobDataC::getCassetteSequenceNo()
    {
        return m_nCassetteSequenceNo;
SourceCode/Bond/Servo/CJobDataC.h
@@ -6,9 +6,11 @@
    {
    public:
        CJobDataC();
        ~CJobDataC();
        virtual ~CJobDataC();
    public:
        void* getOwner();
        void setOwner(void* pOwner);
        int getCassetteSequenceNo();
        void setCassetteSequenceNo(int no);
        std::string& getCassetteId();
@@ -21,6 +23,7 @@
        void setMasterRecipe(const char* pszRecipe);
    private:
        void* m_pOwner;
        int m_nCassetteSequenceNo;
        std::string m_strCassetteId;
        std::string m_strCassetteJudge;
SourceCode/Bond/Servo/CJobDataS.cpp
@@ -30,6 +30,7 @@
        m_nTargetPortNo = 0;
        m_nTargetSlotNo = 0;
        m_pRawData = nullptr;
        m_pOwner = nullptr;
        if (ENABLE_JOBDATAS_RAWDATA) {
            m_pRawData = new char[JOBDATAS_SIZE];
            serialize(m_pRawData, JOBDATAS_SIZE);
@@ -84,6 +85,17 @@
        m_nSourceSlotNo = pScr->m_nSourceSlotNo;
        m_nTargetPortNo = pScr->m_nTargetPortNo;
        m_nTargetSlotNo = pScr->m_nTargetSlotNo;
        m_pOwner = pScr->m_pOwner;
    }
    void* CJobDataS::getOwner()
    {
        return m_pOwner;
    }
    void CJobDataS::setOwner(void* pOwner)
    {
        m_pOwner = pOwner;
    }
    int CJobDataS::getCassetteSequenceNo()
SourceCode/Bond/Servo/CJobDataS.h
@@ -9,9 +9,11 @@
    public:
        CJobDataS();
        CJobDataS::CJobDataS(CJobDataS&& other) noexcept;
        ~CJobDataS();
        virtual ~CJobDataS();
    public:
        void* getOwner();
        void setOwner(void* pOwner);
        void copy(CJobDataS* pScr);
        int getCassetteSequenceNo();
        void setCassetteSequenceNo(int no);
@@ -77,6 +79,7 @@
    private:
        void* m_pOwner;
        int m_nCassetteSequenceNo;
        int m_nJobSequenceNo;
        std::string m_strLotId;
SourceCode/Bond/Servo/CLoadPort.cpp
@@ -16,10 +16,10 @@
    CLoadPort::CLoadPort() : CEquipment()
    {
        m_nIndex = 0;
        m_nType = 1;
        m_nMode = 1;
        m_nCassetteType = 1;
        m_nTransferMode = 1;
        m_portType = PortType::Loading;
        m_portMode = PortMode::InService;
        m_cassetteType = CassetteType::G1;
        m_transferMode = TransferMode::AGVMode;
        m_bEnable = FALSE;
        m_bAutoChangeEnable = FALSE;
    }
@@ -55,6 +55,35 @@
        addPin(SERVO::PinType::OUTPUT, _T("Out2"));
    }
    // å¿…须要实现的虚函数,在此初始化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");
    }
    void CLoadPort::initSteps()
    {
        CEquipment::initSteps();
@@ -88,7 +117,7 @@
            CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    if (code == ROK && pszData != nullptr && size > 0) {
                        m_nType = (unsigned int)CToolUnits::toInt16(pszData);
                        m_portType = (PortType)CToolUnits::toInt16(pszData);
                    }
                    return 0;
                });
@@ -109,7 +138,7 @@
            CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    if (code == ROK && pszData != nullptr && size > 0) {
                        m_nMode = (unsigned int)CToolUnits::toInt16(pszData);
                        m_portMode = (PortMode)CToolUnits::toInt16(pszData);
                    }
                    return 0;
                });
@@ -130,7 +159,7 @@
            CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    if (code == ROK && pszData != nullptr && size > 0) {
                        m_nCassetteType = (unsigned int)CToolUnits::toInt16(pszData);
                        m_cassetteType = (CassetteType)CToolUnits::toInt16(pszData);
                    }
                    return 0;
                });
@@ -151,7 +180,7 @@
            CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
                [&](void* pFrom, int code, const char* pszData, size_t size) -> int {
                    if (code == ROK && pszData != nullptr && size > 0) {
                        m_nTransferMode = (unsigned int)CToolUnits::toInt16(pszData);
                        m_transferMode = (TransferMode)CToolUnits::toInt16(pszData);
                    }
                    return 0;
                });
@@ -358,13 +387,13 @@
        attrubutes.addAttribute(new CAttribute("Index",
            std::to_string(m_nIndex).c_str(), "", weight++));
        attrubutes.addAttribute(new CAttribute("Type",
            getPortTypeDescription(m_nType, strTemp).c_str(), "", weight++));
            getPortTypeDescription(m_portType, strTemp).c_str(), "", weight++));
        attrubutes.addAttribute(new CAttribute("Mode",
            getPortModeDescription(m_nMode, strTemp).c_str(), "", weight++));
            getPortModeDescription(m_portMode, strTemp).c_str(), "", weight++));
        attrubutes.addAttribute(new CAttribute("CassetteType",
            getPortCassetteTypeDescription(m_nCassetteType, strTemp).c_str(), "", weight++));
            getPortCassetteTypeDescription(m_cassetteType, strTemp).c_str(), "", weight++));
        attrubutes.addAttribute(new CAttribute("TransferMode",
            getPortTransferModeDescription(m_nTransferMode, strTemp).c_str(), "", weight++));
            getPortTransferModeDescription(m_transferMode, strTemp).c_str(), "", weight++));
        attrubutes.addAttribute(new CAttribute("Enable",
            m_bEnable ? "Eanble" : "Disable", "", weight++));
        attrubutes.addAttribute(new CAttribute("Auto Change",
@@ -374,21 +403,6 @@
    int CLoadPort::recvIntent(CPin* pPin, CIntent* pIntent)
    {
        return __super::recvIntent(pPin, pIntent);
    }
    int CLoadPort::outputGlass(int port)
    {
        return __super::outputGlass(port);
    }
    BOOL CLoadPort::glassWillArrive(CGlass* pGlass)
    {
        BOOL bRet = __super::glassWillArrive(pGlass);
        if (!bRet) {
            return FALSE;
        }
        return (m_glassList.size() < 8);
    }
    int CLoadPort::sendCassetteCtrlCmd(short cmd,
@@ -441,24 +455,24 @@
        return m_bEnable;
    }
    int CLoadPort::getPortType()
    PortType CLoadPort::getPortType()
    {
        return m_nType;
        return m_portType;
    }
    int CLoadPort::getPortMode()
    PortMode CLoadPort::getPortMode()
    {
        return m_nMode;
        return m_portMode;
    }
    int CLoadPort::getCessetteType()
    CassetteType CLoadPort::getCessetteType()
    {
        return m_nCassetteType;
        return m_cassetteType;
    }
    int CLoadPort::getTransferMode()
    TransferMode CLoadPort::getTransferMode()
    {
        return m_nTransferMode;
        return m_transferMode;
    }
    BOOL CLoadPort::isAutoChange()
@@ -510,9 +524,9 @@
     6: Buffer Port-Un-loader in Buffer Type
     7: Unloading Partial Port
     */
    std::string& CLoadPort::getPortTypeDescription(int portType, std::string& strDescription)
    std::string& CLoadPort::getPortTypeDescription(PortType portType, std::string& strDescription)
    {
        switch (portType) {
        switch ((int)portType) {
        case 1:
            strDescription = _T("Loading Port");
            break;
@@ -550,9 +564,9 @@
     4: InService
     5: TransferReady
     */
    std::string& CLoadPort::getPortModeDescription(int portMode, std::string& strDescription)
    std::string& CLoadPort::getPortModeDescription(PortMode portMode, std::string& strDescription)
    {
        switch (portMode) {
        switch ((int)portMode) {
        case 0:
            strDescription = _T("OutOfService");
            break;
@@ -584,9 +598,9 @@
     2: G2
     3: G1&G2
     */
    std::string& CLoadPort::getPortCassetteTypeDescription(int casseteType, std::string& strDescription)
    std::string& CLoadPort::getPortCassetteTypeDescription(CassetteType casseteType, std::string& strDescription)
    {
        switch (casseteType) {
        switch ((int)casseteType) {
        case 1:
            strDescription = _T("G1");
            break;
@@ -609,9 +623,9 @@
     2: AGV Mode
     3: Stocker Inline Mode
     */
    std::string& CLoadPort::getPortTransferModeDescription(int mode, std::string& strDescription)
    std::string& CLoadPort::getPortTransferModeDescription(TransferMode mode, std::string& strDescription)
    {
        switch (mode) {
        switch ((int)mode) {
        case 1:
            strDescription = _T("MGV Mode");
            break;
@@ -1044,11 +1058,16 @@
    /*
     * ç”Ÿæˆæµ‹è¯•用的玻璃列表
     */
    int CLoadPort::testGenerateGlassList(MaterialsType type, int count, const char* pszPrefix, int startSuffix)
    int CLoadPort::testGenerateGlassList(MaterialsType type, const char* pszPrefix, int startSuffix)
    {
        static unsigned short nJobSequenceNo = 0;
        static unsigned short nCassetteSequenceNo = 0;
        nCassetteSequenceNo++;
        // å¦‚果非空就不生成了
        Lock();
        if (!m_glassList.empty()) {
        if (hasGlass()) {
            Unlock();
            return -1;
        }
@@ -1057,13 +1076,19 @@
        char szBuffer[64];
        int suffix = startSuffix;
        for (int i = 0; i < count; i++) {
        for (int i = 0; i < SLOT_MAX; 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.setMaterialsType((int)type);
            js.setCassetteSequenceNo(nCassetteSequenceNo);
            js.setJobSequenceNo(nJobSequenceNo);
            if (type == MaterialsType::G1) {
                js.setGlass1Id(szBuffer);
            }
@@ -1076,7 +1101,8 @@
            pGlass->setJobDataB(&jb);
            pGlass->setType(type);
            pGlass->setJobDataS(&js);
            addGlassToList(pGlass);
            pGlass->addRef();
            m_slot[i].setContext(pGlass);
        }
        return 0;
SourceCode/Bond/Servo/CLoadPort.h
@@ -17,11 +17,11 @@
        virtual void term();
        virtual void initPins();
        virtual void initSteps();
        virtual void initSlots();
        virtual void onTimer(UINT nTimerid);
        virtual void serialize(CArchive& ar);
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual BOOL glassWillArrive(CGlass* pGlass);
        virtual void onReceiveLBData(const char* pszData, size_t size);
    public:
@@ -36,10 +36,10 @@
        void setIndex(unsigned int index);
        unsigned int getIndex();
        BOOL isEnable();
        int getPortType();
        int getPortMode();
        int getCessetteType();
        int getTransferMode();
        PortType getPortType();
        PortMode getPortMode();
        CassetteType getCessetteType();
        TransferMode getTransferMode();
        BOOL isAutoChange();
        int getPortStatus();
        int getCassetteSequenceNo();
@@ -48,13 +48,13 @@
        int getQTimeFlag();
        int getCassetteMappingState();
        int getCassetteStatus();
        int testGenerateGlassList(MaterialsType type, int count, const char* pszPrefix, int startSuffix);
        int testGenerateGlassList(MaterialsType type, const char* pszPrefix, int startSuffix);
    public:
        static std::string& getPortTypeDescription(int portType, std::string& strDescription);
        static std::string& getPortModeDescription(int portMode, std::string& strDescription);
        static std::string& getPortCassetteTypeDescription(int casseteType, std::string& strDescription);
        static std::string& getPortTransferModeDescription(int mode, std::string& strDescription);
        static std::string& getPortTypeDescription(PortType portType, std::string& strDescription);
        static std::string& getPortModeDescription(PortMode portMode, std::string& strDescription);
        static std::string& getPortCassetteTypeDescription(CassetteType casseteType, std::string& strDescription);
        static std::string& getPortTransferModeDescription(TransferMode mode, std::string& strDescription);
        static std::string& getEnableModeDescription(int mode, std::string& strDescription);
        static std::string& getPortStatusDescription(int portStatus, std::string& strDescription);
        static std::string& getLoadingCassetteTypeDescription(int type, std::string& strDescription);
@@ -63,7 +63,6 @@
        static std::string& getCassetteStatusDescription(int state, std::string& strDescription);
    public:
        virtual int outputGlass(int port);
        int sendCassetteCtrlCmd(short cmd,
            short* jobExistence,
            int jobExistenceSize,
@@ -77,10 +76,10 @@
    private:
        unsigned int m_nIndex;
        int m_nType;
        int m_nMode;
        int m_nCassetteType;
        int m_nTransferMode;
        PortType m_portType;
        PortMode m_portMode;
        CassetteType m_cassetteType;
        TransferMode m_transferMode;
        BOOL m_bEnable;
        BOOL m_bAutoChangeEnable;
        CPortStatusReport m_portStatusReport;
SourceCode/Bond/Servo/CMaster.cpp
@@ -6,6 +6,15 @@
namespace SERVO {
    CMaster* g_pMaster = NULL;
    unsigned __stdcall DispatchThreadFunction(LPVOID lpParam)
    {
        if (g_pMaster != NULL) {
            return g_pMaster->DispatchProc();
        }
        return 0;
    }
    unsigned __stdcall ReadBitsThreadFunction(LPVOID lpParam)
    {
        if (g_pMaster != NULL) {
@@ -24,12 +33,22 @@
    CMaster::CMaster()
    {
        m_listener = {nullptr, nullptr, nullptr, nullptr, nullptr};
        m_listener = {};
        m_bDataModify = FALSE;
        m_hEventReadBitsThreadExit[0] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        m_hEventReadBitsThreadExit[1] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        m_hReadBitsThreadHandle = nullptr;
        m_nReadBitsThreadAddr = 0;
        m_hDispatchEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        m_hEventDispatchThreadExit[0] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        m_hEventDispatchThreadExit[1] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        m_hDispatchThreadHandle = nullptr;
        m_nDispatchThreadAddr = 0;
        m_ullStartTime = 0;
        m_ullRunTime = 0;
        m_state = MASTERSTATE::READY;
        m_pActiveRobotTask = nullptr;
        InitializeCriticalSection(&m_criticalSection);
    }
    CMaster::~CMaster()
@@ -43,15 +62,33 @@
            ::CloseHandle(m_hEventReadBitsThreadExit[1]);
            m_hEventReadBitsThreadExit[1] = nullptr;
        }
        if (m_hDispatchEvent != nullptr) {
            ::CloseHandle(m_hDispatchEvent);
            m_hDispatchEvent = nullptr;
        }
        if (m_hEventDispatchThreadExit[0] != nullptr) {
            ::CloseHandle(m_hEventDispatchThreadExit[0]);
            m_hEventDispatchThreadExit[0] = nullptr;
        }
        if (m_hEventDispatchThreadExit[1] != nullptr) {
            ::CloseHandle(m_hEventDispatchThreadExit[1]);
            m_hEventDispatchThreadExit[1] = nullptr;
        }
        DeleteCriticalSection(&m_criticalSection);
    }
    void CMaster::setListener(MasterListener listener)
    {
        m_listener.onEqAlive = listener.onEqAlive;
        m_listener.onEqCimStateChanged = listener.onEqCimStateChanged;
        m_listener.onEqAlarm = listener.onEqAlarm;
        m_listener.onEqVcrEventReport = listener.onEqVcrEventReport;
        m_listener.onEqDataChanged = listener.onEqDataChanged;
        m_listener = listener;
    }
    CRobotTask* CMaster::getActiveRobotTask()
    {
        return m_pActiveRobotTask;
    }
    int CMaster::init()
@@ -159,6 +196,12 @@
        SetTimer(NULL, 1, 250, (TIMERPROC)MasterTimerProc);
        // è°ƒåº¦çº¿ç¨‹
        m_hDispatchThreadHandle = (HANDLE)_beginthreadex(NULL, 0, SERVO::DispatchThreadFunction, this,
            0, &m_nDispatchThreadAddr);
        // ç›‘控bit线程
        m_hReadBitsThreadHandle = (HANDLE)_beginthreadex(NULL, 0, SERVO::ReadBitsThreadFunction, this,
            0, &m_nReadBitsThreadAddr);
@@ -170,7 +213,9 @@
    int CMaster::term()
    {
        SetEvent(m_hEventReadBitsThreadExit[0]);
        SetEvent(m_hEventDispatchThreadExit[0]);
        ::WaitForSingleObject(m_hEventReadBitsThreadExit[1], INFINITE);
        ::WaitForSingleObject(m_hEventDispatchThreadExit[1], INFINITE);
        LOGI("<Master>正在结束程序.");
        for (auto item : m_listEquipment) {
@@ -178,6 +223,12 @@
        }
        saveCache();
        lock();
        if (m_pActiveRobotTask != nullptr) {
            delete m_pActiveRobotTask;
            m_pActiveRobotTask = nullptr;
        }
        unlock();
        for (auto item : m_listEquipment) {
            delete item;
@@ -185,6 +236,167 @@
        m_listEquipment.clear();
        return 0;
    }
    int CMaster::start()
    {
        if (m_state != MASTERSTATE::READY) {
            return -1;
        }
        setState(MASTERSTATE::STARTING);
        m_ullStartTime = GetTickCount64();
        return 0;
    }
    int CMaster::stop()
    {
        // è¿è¡Œæ—¶é—´ä¸ºç´¯åŠ ç»“æžœï¼Œæœ¬æ¬¡åœæ­¢æ—¶åˆ·æ–°ï¼›
        if (m_state != MASTERSTATE::RUNNING) {
            return -1;
        }
        m_ullRunTime += (GetTickCount64() - m_ullStartTime);
        setState(MASTERSTATE::STOPPING);
        return 0;
    }
    ULONGLONG CMaster::getRunTime()
    {
        if (m_state == MASTERSTATE::RUNNING)
            return m_ullRunTime + (GetTickCount64() - m_ullStartTime);
        else
            return m_ullRunTime;
    }
    MASTERSTATE CMaster::getState()
    {
        return m_state;
    }
    unsigned CMaster::DispatchProc()
    {
        while (1) {
            // å¾…退出信号或时间到
            HANDLE hEvents[] = { m_hEventDispatchThreadExit[0], m_hDispatchEvent };
            int nRet = WaitForMultipleObjects(2, hEvents, FALSE, 1000);
            if (nRet == WAIT_OBJECT_0) {
                break;
            }
            // å¦‚果状态为STARTING,开始工作并切换到RUNNING状态
            lock();
            if (m_state == MASTERSTATE::STARTING) {
                unlock();
                Sleep(1000);
                setState(MASTERSTATE::RUNNING);
                continue;
            }
            // å¤„理完成当前事务后,切换到停止或就绪状态
            else if (m_state == MASTERSTATE::STOPPING) {
                unlock();
                Sleep(1000);
                setState(MASTERSTATE::READY);
                continue;
            }
            // è°ƒåº¦é€»è¾‘处理
            else if (m_state == MASTERSTATE::RUNNING) {
                unlock();
                LOGI("调度处理中...");
                lock();
                if (m_pActiveRobotTask != nullptr) {
                    unlock();
                    // æ£€æµ‹åˆ°å½“前有正在下午的任务,确保当前任务完成或中止后继续
                    LOGI("检测到当前有正在下午的任务,确保当前任务完成或中止后继续...");
                    continue;
                }
                // LoadPort -> Fliper(G2)
                CLoadPort* pLoadPort1 = (CLoadPort*)getEquipment(EQ_ID_LOADPORT1);
                CLoadPort* pLoadPort2 = (CLoadPort*)getEquipment(EQ_ID_LOADPORT2);
                CFliper* pFliper = (CFliper*)getEquipment(EQ_ID_FLIPER);
                CVacuumBake* pVacuumBack = (CVacuumBake*)getEquipment(EQ_ID_VACUUMBAKE);
                ASSERT(pLoadPort1);
                ASSERT(pLoadPort2);
                ASSERT(pFliper);
                ASSERT(pVacuumBack);
                m_pActiveRobotTask = createTransferTask(pLoadPort1, pFliper);
                if (m_pActiveRobotTask != nullptr) {
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    LOGI("创建新任务<%s>...", strDescription.c_str());
                    continue;
                }
                m_pActiveRobotTask = createTransferTask(pLoadPort2, pFliper);
                if (m_pActiveRobotTask != nullptr) {
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    LOGI("创建新任务<%s>...", strDescription.c_str());
                    continue;
                }
                // LoadPort -> VacuumBake(G1)
                m_pActiveRobotTask = createTransferTask(pLoadPort1, pVacuumBack);
                if (m_pActiveRobotTask != nullptr) {
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    LOGI("创建新任务1<%s>...", strDescription.c_str());
                    continue;
                }
                m_pActiveRobotTask = createTransferTask(pLoadPort2, pVacuumBack);
                if (m_pActiveRobotTask != nullptr) {
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    LOGI("创建新任务2<%s>...", strDescription.c_str());
                    continue;
                }
                // Fliper(G2) -> Aligner
                // VacuumBake(G1) -> Aligner
                // Aligner -> Bonder
                // Bonder -> BakeCooling
                // BakeCooling ->Measurement
                // Measurement -> LoadPort
                unlock();
            }
            unlock();
        }
        SetEvent(m_hEventDispatchThreadExit[1]);
        // _endthreadex(0);
        TRACE("CMaster::DispatchProc çº¿ç¨‹é€€å‡º\n");
        return 0;
    }
@@ -248,11 +460,102 @@
                m_listener.onEqVcrEventReport(this, p, p2);
            }
        };
        listener.onPreFethedOutJob = [&](void* pEquipment, CJobDataB* pJobDataB) -> BOOL {
            CEquipment* p = (CEquipment*)pEquipment;
            // å–片,更新当前搬送任务
            BOOL bOk = FALSE;
            lock();
            if (m_pActiveRobotTask != nullptr) {
                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()) {
                            bOk = TRUE;
                            LOGI("<CMaster>onPreFethedOutJob, å·²æ ¡éªŒæ•°æ®ä¸€è‡´æ€§.");
                        }
                    }
                }
                else if (p->getID() == EQ_ID_ARM_TRAY1 || p->getID() == EQ_ID_ARM_TRAY2) {
                    bOk = TRUE;
                }
            }
            unlock();
            if (!bOk) {
                LOGE("<CMaster>onPreFethedOutJob, æ•°æ®æ ¡éªŒå¤±è´¥.");
            }
            return bOk;
        };
        listener.onPreStoredJob = [&](void* pEquipment, CJobDataB* pJobDataB, short& slot) -> BOOL {
            CEquipment* p = (CEquipment*)pEquipment;
            // æ”¾ç‰‡ï¼Œæ›´æ–°å½“前搬送任务
            BOOL bOk = FALSE;
            lock();
            if (m_pActiveRobotTask != nullptr) {
                if (m_pActiveRobotTask->getTarPosition() == p->getID()) {
                    CGlass* pGlass = p->getGlassFromSlot(m_pActiveRobotTask->getTarSlot());
                    if (pGlass == nullptr) {
                        bOk = TRUE;
                        slot = m_pActiveRobotTask->getTarSlot();
                        LOGI("<CMaster>onPreFethedOutJob, å·²æ ¡éªŒæ•°æ®ä¸€è‡´æ€§.");
                    }
                }
                else if (p->getID() == EQ_ID_ARM_TRAY1 || p->getID() == EQ_ID_ARM_TRAY2) {
                    slot = 1;
                    bOk = TRUE;
                }
            }
            unlock();
            if (!bOk) {
                LOGE("<CMaster>onPreFethedOutJob, æ•°æ®æ ¡éªŒå¤±è´¥.");
            }
            return bOk;
        };
        listener.onDataChanged = [&](void* pEquipment, int code) -> void {
            m_bDataModify = TRUE;
            CEquipment* p = (CEquipment*)pEquipment;
            if (m_listener.onEqDataChanged != nullptr) {
                m_listener.onEqDataChanged(this, p, 0);
            }
            // å–放片,更新当前搬送任务
            if (code == EDCC_FETCHOUT_JOB) {
                lock();
                if (m_pActiveRobotTask != nullptr && m_pActiveRobotTask->getSrcPosition() == p->getID()) {
                    m_pActiveRobotTask->fetchOut();
                    LOGI("开始取片...");
                }
                unlock();
            }
            else if (code == EDCC_STORED_JOB) {
                lock();
                if (m_pActiveRobotTask != nullptr && m_pActiveRobotTask->getTarPosition() == p->getID()) {
                    m_pActiveRobotTask->stored();
                    m_pActiveRobotTask->completed();
                    LOGI("放片完成...");
                    // å®Œæˆæ­¤æ¡æ¬é€ä»»åŠ¡ï¼Œä½†è¦æŠŠæ•°æ®å’Œæ¶ˆæ¯ä¸ŠæŠ›åº”ç”¨å±‚
                    unlock();
                    lock();
                    delete m_pActiveRobotTask;
                    m_pActiveRobotTask = nullptr;
                }
                unlock();
            }
        };
@@ -656,4 +959,36 @@
            item->serialize(ar);
        }
    }
    void CMaster::setState(MASTERSTATE state)
    {
        m_state = state;
        if (m_listener.onMasterStateChanged != nullptr) {
            m_listener.onMasterStateChanged(this, m_state);
        }
    }
    static int taskSeqNo = 0;
    CRobotTask* CMaster::createTransferTask(CEquipment* pSrcEq, CEquipment* pTarEq)
    {
        CRobotTask* pTask = nullptr;
        CSlot* pSrcSlot, * pTarSlot;
        pTarSlot = pTarEq->getAvailableSlotForGlass(MaterialsType::G1);
        pSrcSlot = pSrcEq->getNonEmptySlot(MaterialsType::G1);
        if (pSrcSlot == nullptr || nullptr == pTarSlot) {
            pTarSlot = pTarEq->getAvailableSlotForGlass(MaterialsType::G2);
            pSrcSlot = pSrcEq->getNonEmptySlot(MaterialsType::G2);
        }
        if (pSrcSlot != nullptr && nullptr != pTarSlot) {
            pTask = new CRobotTask();
            pTask->setContext(pSrcSlot->getContext());
            pTask->setRobotTransferParam(++taskSeqNo, 1, pSrcSlot->getPosition(),
                pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo());
        }
        return pTask;
    }
}
SourceCode/Bond/Servo/CMaster.h
@@ -12,9 +12,18 @@
#include "CArm.h"
#include "CArmTray.h"
#include "CCLinkIEControl.h"
#include "CRobotTask.h"
namespace SERVO {
    enum MASTERSTATE {
        READY = 0,
        STARTING,
        RUNNING,
        STOPPING
    };
    typedef std::function<void(void* pMaster, MASTERSTATE state)> ONMASTERSTATECHANGED;
    typedef std::function<void(void* pMaster, CEquipment* pEiuipment, BOOL bAlive)> ONEQALIVE;
    typedef std::function<void(CStep* pStep, int code, void* pData)> ONEQSTEPEVENT;
    typedef std::function<void(void* pMaster, CEquipment* pEquipment, int state, int alarmId, int unitId, int level)> ONEQALARM;
@@ -22,6 +31,7 @@
    typedef std::function<void(void* pMaster, CEquipment* pEquipment, int code)> ONEQDATACHANGED;
    typedef struct _MasterListener
    {
        ONMASTERSTATECHANGED    onMasterStateChanged;
        ONEQALIVE                onEqAlive;
        ONEQALIVE                onEqCimStateChanged;
        ONEQALARM               onEqAlarm;
@@ -33,13 +43,19 @@
    {
    public:
        CMaster();
        ~CMaster();
        virtual ~CMaster();
    public:
        void setListener(MasterListener listener);
        CRobotTask* getActiveRobotTask();
        int init();
        int term();
        int start();
        int stop();
        ULONGLONG getRunTime();
        MASTERSTATE getState();
        unsigned DispatchProc();
        unsigned ReadBitsProc();
        void onTimer(UINT nTimerid);
        std::list<CEquipment*>& getEquipmentList();
@@ -47,6 +63,8 @@
        void setCacheFilepath(const char* pszFilepath);
    private:
        inline void lock() { EnterCriticalSection(&m_criticalSection); }
        inline void unlock() { LeaveCriticalSection(&m_criticalSection); }
        int addToEquipmentList(CEquipment* pEquipment);
        CLoadPort* addLoadPort(int index);
        CFliper* addFliper();
@@ -63,8 +81,11 @@
        int saveCacheAndBackups();
        int readCache();
        void serialize(CArchive& ar);
        void setState(MASTERSTATE state);
        CRobotTask* createTransferTask(CEquipment* pSrcEq, CEquipment* pTarEq);
    private:
        CRITICAL_SECTION m_criticalSection;
        MasterListener m_listener;
        CCCLinkIEControl m_cclink;
        std::list<CEquipment*> m_listEquipment;
@@ -72,9 +93,25 @@
        BOOL m_bDataModify;
    private:
        /* ç›‘控比特位的线程*/
        HANDLE m_hEventReadBitsThreadExit[2];
        HANDLE m_hReadBitsThreadHandle;
        unsigned m_nReadBitsThreadAddr;
        // è°ƒåº¦çº¿ç¨‹
        HANDLE m_hDispatchEvent;
        HANDLE m_hEventDispatchThreadExit[2];
        HANDLE m_hDispatchThreadHandle;
        unsigned m_nDispatchThreadAddr;
        // å¯åŠ¨æ—¶é—´ï¼Œè¿è¡Œæ—¶é—´ï¼ŒçŠ¶æ€
        ULONGLONG m_ullStartTime;
        ULONGLONG m_ullRunTime;
        MASTERSTATE m_state;
        // å½“前任务和已完成任务列表
        CRobotTask* m_pActiveRobotTask;
        std::list< CRobotTask* > m_listTask;
    };
}
SourceCode/Bond/Servo/CMeasurement.cpp
@@ -38,6 +38,15 @@
        addPin(SERVO::PinType::OUTPUT, _T("Out2"));
    }
    // å¿…须要实现的虚函数,在此初始化Slot信息
    void CMeasurement::initSlots()
    {
        m_slot[0].enable();
        m_slot[0].setPosition(m_nID);
        m_slot[0].setNo(1);
        m_slot[0].setName("Slot 1");
    }
    void CMeasurement::onTimer(UINT nTimerid)
    {
        CEquipment::onTimer(nTimerid);
@@ -56,16 +65,6 @@
    int CMeasurement::recvIntent(CPin* pPin, CIntent* pIntent)
    {
        return __super::recvIntent(pPin, pIntent);
    }
    BOOL CMeasurement::glassWillArrive(CGlass* pGlass)
    {
        BOOL bRet = __super::glassWillArrive(pGlass);
        if (!bRet) {
            return FALSE;
        }
        return m_glassList.empty();
    }
    int CMeasurement::getIndexerOperationModeBaseValue()
SourceCode/Bond/Servo/CMeasurement.h
@@ -15,11 +15,11 @@
        virtual void init();
        virtual void term();
        virtual void initPins();
        virtual void initSlots();
        virtual void onTimer(UINT nTimerid);
        virtual void serialize(CArchive& ar);
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual BOOL glassWillArrive(CGlass* pGlass);
        virtual int getIndexerOperationModeBaseValue();
    };
SourceCode/Bond/Servo/CMyStatusbar.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,117 @@
// CMyStatusbar.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "Servo.h"
#include "CMyStatusbar.h"
#include "afxdialogex.h"
// CMyStatusbar å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CMyStatusbar, CDialogEx)
CMyStatusbar::CMyStatusbar(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_STATUSBAR, pParent)
{
    m_crBkgnd = STATUSBAR_BK_NORMAL;
}
CMyStatusbar::~CMyStatusbar()
{
}
void CMyStatusbar::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMyStatusbar, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
END_MESSAGE_MAP()
// CMyStatusbar æ¶ˆæ¯å¤„理程序
void CMyStatusbar::setBackgroundColor(COLORREF color)
{
    if (m_brBkgnd.GetSafeHandle() != nullptr) {
        m_brBkgnd.DeleteObject();
    }
    m_brBkgnd.CreateSolidBrush(color);
    Invalidate();
    UpdateWindow();
}
void CMyStatusbar::setForegroundColor(COLORREF cr)
{
    m_crForeground = cr;
    Invalidate();
    UpdateWindow();
}
void CMyStatusbar::setRunTimeText(const char* pszText)
{
    SetDlgItemText(IDC_LABEL_RUNTIME, pszText);
}
BOOL CMyStatusbar::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CMyStatusbar::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    // TODO:  åœ¨æ­¤æ›´æ”¹ DC çš„任何特性
    if (nCtlColor == CTLCOLOR_STATIC) {
        pDC->SetBkMode(TRANSPARENT);
        pDC->SetBkColor(m_crBkgnd);
        pDC->SetTextColor(m_crForeground);
    }
    if (m_brBkgnd.GetSafeHandle() == nullptr) {
        m_brBkgnd.CreateSolidBrush(m_crBkgnd);
    }
    return (HBRUSH)m_brBkgnd;
}
void CMyStatusbar::OnDestroy()
{
    CDialogEx::OnDestroy();
    // TODO: åœ¨æ­¤å¤„添加消息处理程序代码
}
void CMyStatusbar::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (nullptr == GetDlgItem(IDC_LABEL_RUNTIME)) return;
    Resize();
}
void CMyStatusbar::Resize()
{
    CRect rcClient, rcItem;
    CWnd* pItem = nullptr;
    int x;
    GetClientRect(&rcClient);
    x = 120;
    pItem = GetDlgItem(IDC_LABEL_RUNTIME);
    pItem->GetClientRect(rcItem);
    pItem->MoveWindow(x, (rcClient.Height() - rcItem.Height()) / 2, rcItem.Width(), rcItem.Height());
}
SourceCode/Bond/Servo/CMyStatusbar.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
#pragma once
// CMyStatusbar å¯¹è¯æ¡†
class CMyStatusbar : public CDialogEx
{
    DECLARE_DYNAMIC(CMyStatusbar)
public:
    CMyStatusbar(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CMyStatusbar();
public:
    void setBackgroundColor(COLORREF color);
    void setForegroundColor(COLORREF cr);
    void setRunTimeText(const char* pszText);
private:
    void Resize();
private:
    COLORREF m_crForeground;
    COLORREF m_crBkgnd;
    CBrush m_brBkgnd;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_STATUSBAR };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnDestroy();
    afx_msg void OnSize(UINT nType, int cx, int cy);
};
SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -13,8 +13,6 @@
#include "CPagePortStatus.h"
#include "CPageCassetteCtrlCmd.h"
#include "CJobDataB.h"
#include "CRobotCmdContainerDlg.h"
#include "CRobotCmdTestDlg.h"
// CPageGraph2 å¯¹è¯æ¡†
@@ -67,7 +65,7 @@
                SERVO::CEquipment* pEquipment = nullptr;
                if (pAny->getPtrValue("ptr", (void*&)pEquipment)) {
                    if (pEquipment != nullptr) {
                        m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, !pEquipment->isGlassListEmpty());
                        m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, pEquipment->hasGlass());
                    }
                }
            }
@@ -206,22 +204,29 @@
        // æµ‹è¯•
        else if (nCmd == ID_EQSGRAPHITEM_TEST1) {
            BOOL bTestGenerate = FALSE;
            SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
            if (pEquipment->getID() == EQ_ID_LOADPORT1) {
                ((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G1, 10,
            if (pEquipment->getID() == EQ_ID_LOADPORT1 && !pEquipment->hasGlass()) {
                ((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G1,
                    "P20250320G1X", 1);
                bTestGenerate = TRUE;
            }
            else if (pEquipment->getID() == EQ_ID_LOADPORT2) {
                ((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G2, 10,
            else if (pEquipment->getID() == EQ_ID_LOADPORT2 && !pEquipment->hasGlass()) {
                ((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G2,
                    "P20250320G2X", 1);
                bTestGenerate = TRUE;
            }
            SERVO::CGlass* pGlass = pEquipment->getFrontGlass();
            if (pGlass != nullptr) {
            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->fetchedOutJob(pJobDataB);
                        pEquipment->onFetchedOutJob(0, pJobDataB);
                    pEquipment->onSentOutJob(0, pJobDataS);
                    }
                }
            }
        }
@@ -229,7 +234,7 @@
            SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
            SERVO::CArm* pArm = (SERVO::CArm*)pEquipment->getArm();
            if (pArm != nullptr) {
                SERVO::CGlass* pGlass = pArm->getFrontGlass();
                SERVO::CGlass* pGlass = pArm->getAnyGlass();
                if (pGlass != nullptr) {
                    SERVO::CJobDataB* pJobDataB = pGlass->getJobDataB();
                    SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS();
@@ -244,7 +249,7 @@
        else if (nCmd == ID_EQSGRAPHITEM_TEST3) {
            SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
            if (pEquipment != nullptr) {
                SERVO::CGlass* pGlass = pEquipment->getFrontGlass();
                SERVO::CGlass* pGlass = pEquipment->getAnyGlass();
                if (pGlass != nullptr) {
                    SERVO::CProcessData pd;
                    pd.setGlassId(pGlass->getID().c_str());
@@ -254,44 +259,6 @@
        }
        else if (nCmd == ID_EQSGRAPHITEM_TEST4) {
            SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
            /* æµ‹è¯• RobotCMD */
            if (pEquipment->getID() == EQ_ID_EFEM) {
                SERVO::CEFEM* pEFEM = (SERVO::CEFEM*)pEquipment;
                //SERVO::ROBOT_CMD_PARAM cmds[4];
                //cmds[0].sequenceNo = 1;
                //cmds[0].rcmd = (short)SERVO::RCMD::Move;
                //cmds[0].armNo = 1;
                //cmds[0].getPosition = 1;
                //cmds[0].putPosition = 2;
                //cmds[0].getSlotNo = 3;
                //cmds[0].putSlotNo = 4;
                //cmds[0].subCmd = 5;
                //cmds[1].sequenceNo = 2;
                //cmds[1].rcmd = (short)SERVO::RCMD::Transfer;
                //cmds[1].armNo = 2;
                //cmds[1].getPosition = 6;
                //cmds[1].putPosition = 7;
                //cmds[1].getSlotNo = 8;
                //cmds[1].putSlotNo = 9;
                //cmds[1].subCmd = 10;
                //pEFEM->robotCmds(cmds, 2);
                //CRobotCmdContainerDlg dlg;
                //if (dlg.DoModal() == IDOK) {
                //    std::vector<SERVO::ROBOT_CMD_PARAM>& cmds = dlg.GetResultCmds();
                //    if (!cmds.empty()) {
                //        pEFEM->robotCmds(cmds.data(), (int)cmds.size());
                //    }
                //}
                CRobotCmdTestDlg dlg;
                dlg.SetEFEM(pEFEM);
                dlg.DoModal();
            }
            // æµ‹è¯•下发Cim Message
@@ -356,7 +323,7 @@
            
            /*
            SERVO::CGlass* pGlass = pEquipment->getFrontGlass();
            SERVO::CGlass* pGlass = pEquipment->getAnyGlass();
            if (pGlass != nullptr) {
                std::string strDescription;
                SERVO::CPath* pPath = pGlass->getPath();
@@ -462,7 +429,7 @@
        m_pEqsGraphWnd->AddPin(pItem, OUTPIN, outPin->getName().c_str(), (DWORD_PTR)outPin);
    }
    m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, !pEquipment->isGlassListEmpty());
    m_pEqsGraphWnd->ShowItemIndicator((DWORD_PTR)pEquipment, pEquipment->hasGlass());
}
void CPageGraph2::OnTimer(UINT_PTR nIDEvent)
SourceCode/Bond/Servo/CPagePortProperty.cpp
@@ -60,36 +60,36 @@
    
    pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PORT_TYPE);
    for (int i = 1; i <= 7; i++) {
        pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortTypeDescription(i, strTemp).c_str());
        pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortTypeDescription((SERVO::PortType)i, strTemp).c_str());
    }
    int portType = m_pPort->getPortType();
    int portType = (int)m_pPort->getPortType();
    if (1 <= portType && portType <= 7) {
        pComboBox->SetCurSel(portType - 1);
    }
    pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PORT_MODE);
    for (int i = 0; i <= 5; i++) {
        pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortModeDescription(i, strTemp).c_str());
        pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortModeDescription((SERVO::PortMode)i, strTemp).c_str());
    }
    int portMode = m_pPort->getPortMode();
    int portMode = (int)m_pPort->getPortMode();
    if (0 <= portMode && portMode <= 5) {
        pComboBox->SetCurSel(portMode);
    }
    pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PORT_CASSERT_TYPE);
    for (int i = 1; i <= 3; i++) {
        pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortCassetteTypeDescription(i, strTemp).c_str());
        pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortCassetteTypeDescription((SERVO::CassetteType)i, strTemp).c_str());
    }
    int cessetteType = m_pPort->getCessetteType();
    int cessetteType = (int)m_pPort->getCessetteType();
    if (1 <= cessetteType && cessetteType <= 3) {
        pComboBox->SetCurSel(cessetteType - 1);
    }
    pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_PORT_TRANSFER_MODE);
    for (int i = 1; i <= 3; i++) {
        pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortTransferModeDescription(i, strTemp).c_str());
        pComboBox->InsertString(i - 1, SERVO::CLoadPort::getPortTransferModeDescription((SERVO::TransferMode)i, strTemp).c_str());
    }
    int transferMode = m_pPort->getTransferMode();
    int transferMode = (int)m_pPort->getTransferMode();
    if (1 <= transferMode && transferMode <= 3) {
        pComboBox->SetCurSel(transferMode - 1);
    }
SourceCode/Bond/Servo/CPath.h
@@ -7,7 +7,7 @@
    public:
        CPath();
        CPath(unsigned int nSiteId);
        ~CPath();
        virtual ~CPath();
    public:
        void getDescription(std::string& strOut);
SourceCode/Bond/Servo/CPin.cpp
@@ -118,7 +118,7 @@
            return m_pConnectedPin->recvIntent(pIntent);
        }
        return FLOW_REJECT;
        return 0;
    }
    int CPin::recvIntent(CIntent* pIntent)
SourceCode/Bond/Servo/CPortStatusReport.h
@@ -9,7 +9,7 @@
    {
    public:
        CPortStatusReport();
        ~CPortStatusReport();
        virtual ~CPortStatusReport();
    public:
        void copyEx(CPortStatusReport& other);
SourceCode/Bond/Servo/CProcessData.h
@@ -8,7 +8,7 @@
    {
    public:
        CProcessData();
        ~CProcessData();
        virtual ~CProcessData();
    public:
        std::string& getGlassId();
SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
@@ -127,64 +127,64 @@
    // å¿«æ·å‘½ä»¤æ‰§è¡Œæ˜ å°„表
    m_mapCmdExec = {
        {_T("SendHome"), [this](int seq, int, int, int, int, int) {
            return m_pEFEM->SendHome(seq);
        {_T("SendHome"), [this](int seq, int, int, int, int, int, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendHome(seq, onWritedBlock);
        }},
        {_T("SendTransfer"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
            return m_pEFEM->SendTransfer(seq, armNo, getPos, putPos, getSlot, putSlot);
        {_T("SendTransfer"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendTransfer(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
        }},
        {_T("SendMoveToGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
            return m_pEFEM->SendMoveToGet(seq, armNo, pos, slot);
        {_T("SendMoveToGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendMoveToGet(seq, armNo, pos, slot, onWritedBlock);
        }},
        {_T("SendMoveToPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
            return m_pEFEM->SendMoveToPut(seq, armNo, pos, slot);
        {_T("SendMoveToPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendMoveToPut(seq, armNo, pos, slot, onWritedBlock);
        }},
        {_T("SendGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
            return m_pEFEM->SendGet(seq, armNo, pos, slot);
        {_T("SendGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendGet(seq, armNo, pos, slot, onWritedBlock);
        }},
        {_T("SendPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
            return m_pEFEM->SendPut(seq, armNo, pos, slot);
        {_T("SendPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendPut(seq, armNo, pos, slot, onWritedBlock);
        }},
        {_T("SendExchange"), [this](int seq, int armNo, int pos, int, int getSlot, int putSlot) {
            return m_pEFEM->SendExchange(seq, armNo, pos, getSlot, putSlot);
        {_T("SendExchange"), [this](int seq, int armNo, int pos, int, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendExchange(seq, armNo, pos, getSlot, putSlot, onWritedBlock);
        }},
        {_T("SendCommandClear"), [this](int seq, int, int, int, int, int) {
            return m_pEFEM->SendCommandClear(seq);
        {_T("SendCommandClear"), [this](int seq, int, int, int, int, int, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendCommandClear(seq, onWritedBlock);
        }},
        {_T("SendBatchGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
            return m_pEFEM->SendBatchGet(seq, pos, slot);
        {_T("SendBatchGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendBatchGet(seq, pos, slot, onWritedBlock);
        }},
        {_T("SendBatchPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
            return m_pEFEM->SendBatchPut(seq, pos, slot);
        {_T("SendBatchPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendBatchPut(seq, pos, slot, onWritedBlock);
        }},
        {_T("SendMoveToGetAndHome"), [this](int seq, int armNo, int pos, int, int slot, int) {
            return m_pEFEM->SendMoveToGetAndHome(seq, armNo, pos, slot);
        {_T("SendMoveToGetAndHome"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendMoveToGetAndHome(seq, armNo, pos, slot, onWritedBlock);
        }},
        {_T("SendMoveToPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot) {
            return m_pEFEM->SendMoveToPutAndHome(seq, armNo, pos, slot);
        {_T("SendMoveToPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendMoveToPutAndHome(seq, armNo, pos, slot, onWritedBlock);
        }},
        {_T("SendTransferAndHome"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
            return m_pEFEM->SendTransferAndHome(seq, armNo, getPos, putPos, getSlot, putSlot);
        {_T("SendTransferAndHome"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendTransferAndHome(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
        }},
        {_T("SendGetAndPut"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
            return m_pEFEM->SendGetAndPut(seq, armNo, getPos, putPos, getSlot, putSlot);
        {_T("SendGetAndPut"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendGetAndPut(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
        }},
        {_T("SendPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot) {
            return m_pEFEM->SendPutAndHome(seq, armNo, pos, slot);
        {_T("SendPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
            return m_pEFEM->robotSendPutAndHome(seq, armNo, pos, slot, onWritedBlock);
        }}
    };
@@ -333,7 +333,16 @@
    // æŸ¥æ‰¾å‡½æ•°å¹¶æ‰§è¡Œ
    auto it = m_mapCmdExec.find(cmdName);
    if (it != m_mapCmdExec.end() && nullptr != m_pEFEM) {
        int ret = it->second(1, armNo, getPos, getSlot, putPos, putSlot);
        int ret = it->second(1, armNo, getPos, getSlot, putPos, putSlot, [&](int code) -> int {
            if (code == WOK) {
                AppendLogLineRichStyled(_T("已收到Robot回应!"), LOG_COLOR_SUCCESS);
            }
            else {
                AppendLogLineRichStyled(_T("未收到Robot回应!"), LOG_COLOR_ERROR);
            }
            return 0;
            });
        CString log;
        if (ret == 0) {
SourceCode/Bond/Servo/CRobotCmdTestDlg.h
@@ -3,7 +3,7 @@
#include <afxrich.h>
// å®šä¹‰å‘½ä»¤å‡½æ•°æŒ‡é’ˆç±»åž‹ï¼ˆseq, armNo, getPos, getSlot, putPos, putSlot)
using CmdFunc = std::function<int(int, int, int, int, int, int)>;
using CmdFunc = std::function<int(int, int, int, int, int, int, SERVO::ONWRITED onWritedBlock)>;
// è¾“入控件状态
struct QuickCmdFieldMask {
SourceCode/Bond/Servo/CRobotTask.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,167 @@
#include "stdafx.h"
#include "CRobotTask.h"
#include "ToolUnits.h"
namespace SERVO {
    CRobotTask::CRobotTask()
    {
        generateId(m_strId);
        m_state = ROBOT_TASK_STATE::Ready;
        m_timeCreate = CToolUnits::getTimestamp();
        m_timeFetchOut = 0;
        m_timeStored = 0;
        m_timeFinish = 0;
        m_pContext = nullptr;
    }
    CRobotTask::~CRobotTask()
    {
        if (m_pContext != nullptr) {
            m_pContext->release();
            m_pContext = nullptr;
        }
    }
    std::string CRobotTask::getDescription() const
    {
        std::string strOut = "CRobotTask<ID:";
        strOut = strOut + std::to_string(m_robotCmdParam.sequenceNo);
        strOut = strOut + ",Arm:";
        strOut = strOut + std::to_string(m_robotCmdParam.armNo);
        strOut = strOut + ",GetPossion:";
        strOut = strOut + std::to_string(m_robotCmdParam.getPosition);
        strOut = strOut + ",GetSlot:";
        strOut = strOut + std::to_string(m_robotCmdParam.getSlotNo);
        strOut = strOut + ",PutPossion:";
        strOut = strOut + std::to_string(m_robotCmdParam.putPosition);
        strOut = strOut + ",PutSlot:";
        strOut = strOut + std::to_string(m_robotCmdParam.putSlotNo);
        strOut = strOut + ">";
        return strOut;
    }
    void CRobotTask::setContext(CContext* pContext)
    {
        if (pContext != nullptr) {
            pContext->release();
        }
        m_pContext = pContext;
        if (m_pContext != nullptr) {
            m_pContext->addRef();
        }
    }
    CContext* CRobotTask::getContext()
    {
        return m_pContext;
    }
    std::string& CRobotTask::generateId(std::string& out)
    {
        char szBuffer[256];
        CTime time = CTime::GetCurrentTime();
        __int64 nTick = 0;
        QueryPerformanceCounter((LARGE_INTEGER*)&nTick);
        sprintf_s(szBuffer, 256, "%d%02d%02d%02d%02d%02d%010llu", time.GetYear(),
            time.GetMonth(), time.GetDay(), time.GetHour(), time.GetMinute(), time.GetSecond(),
            nTick % 10000000000);
        out = szBuffer;
        return out;
    }
    std::string& CRobotTask::getId()
    {
        return m_strId;
    }
    void CRobotTask::setRobotTransferParam(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot)
    {
        m_robotCmdParam = {};
        m_robotCmdParam.sequenceNo = static_cast<short>(seq);
        m_robotCmdParam.rcmd = static_cast<short>(SERVO::RCMD::Transfer);
        m_robotCmdParam.armNo = static_cast<short>(armNo);
        m_robotCmdParam.getPosition = static_cast<short>(fromPos);
        m_robotCmdParam.getSlotNo = static_cast<short>(fromSlot);
        m_robotCmdParam.putPosition = static_cast<short>(toPos);
        m_robotCmdParam.putSlotNo = static_cast<short>(toSlot);
    }
    ROBOT_CMD_PARAM& CRobotTask::getRobotCmdParam()
    {
        return m_robotCmdParam;
    }
    time_t CRobotTask::getCreateTime()
    {
        return m_timeCreate;
    }
    time_t CRobotTask::getFetchoutTime()
    {
        return m_timeFetchOut;
    }
    time_t CRobotTask::getStoredTime()
    {
        return m_timeStored;
    }
    time_t CRobotTask::getFinishTime()
    {
        return m_timeFinish;
    }
    ROBOT_TASK_STATE CRobotTask::getState()
    {
        return m_state;
    }
    void CRobotTask::completed()
    {
        m_state = ROBOT_TASK_STATE::Completed;
    }
    void CRobotTask::error()
    {
        m_state = ROBOT_TASK_STATE::Error;
    }
    void CRobotTask::abort()
    {
        m_state = ROBOT_TASK_STATE::Abort;
    }
    int CRobotTask::getSrcPosition()
    {
        return m_robotCmdParam.getPosition;
    }
    int CRobotTask::getTarPosition()
    {
        return m_robotCmdParam.putPosition;
    }
    int CRobotTask::getSrcSlot()
    {
        return m_robotCmdParam.getSlotNo;
    }
    int CRobotTask::getTarSlot()
    {
        return m_robotCmdParam.putSlotNo;
    }
    void CRobotTask::fetchOut()
    {
        m_timeFetchOut = CToolUnits::getTimestamp();;
    }
    void CRobotTask::stored()
    {
        m_timeStored = CToolUnits::getTimestamp();;
    }
}
SourceCode/Bond/Servo/CRobotTask.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
#pragma once
#include "ServoCommo.h"
#include "Context.h"
namespace SERVO {
    class CRobotTask
    {
    public:
        CRobotTask();
        virtual ~CRobotTask();
    public:
        std::string& getId();
        std::string getDescription() const;
        void setContext(CContext* pContext);
        CContext* getContext();
        void setRobotTransferParam(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot);
        ROBOT_CMD_PARAM& getRobotCmdParam();
        time_t getCreateTime();
        time_t getFetchoutTime();
        time_t getStoredTime();
        time_t getFinishTime();
        ROBOT_TASK_STATE getState();
        void completed();
        void error();
        void abort();
        int getSrcPosition();
        int getSrcSlot();
        int getTarPosition();
        int getTarSlot();
        // ä»Žæºåœ°æ‹”片
        void fetchOut();
        // åœ¨ç›®çš„地放片
        void stored();
    private:
        static std::string& generateId(std::string& out);
    private:
        ROBOT_TASK_STATE m_state;                    /* ä»»åŠ¡çŠ¶æ€ */
        std::string m_strId;
        time_t m_timeCreate;                        /* åˆ›å»ºæ—¶é—´ */
        time_t m_timeFetchOut;                        /* å–片时间*/
        time_t m_timeStored;                        /* æ”¾ç‰‡æ—¶é—´ */
        time_t m_timeFinish;                        /* ç»“束时间 */
        ROBOT_CMD_PARAM m_robotCmdParam;            /* å‚æ•° */
        CContext* m_pContext;
    };
}
SourceCode/Bond/Servo/CSlot.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,152 @@
#include "stdafx.h"
#include "CSlot.h"
namespace SERVO {
    CSlot::CSlot()
    {
        m_nNo = 0;
        m_materialsType = MaterialsType::G1G2;
        m_pContext = nullptr;
        m_bEnable = FALSE;
        m_bLock = FALSE;
        m_pContext = nullptr;
    }
    CSlot::~CSlot()
    {
        if (m_pContext != nullptr) {
            m_pContext->release();
            m_pContext = nullptr;
        }
    }
    BOOL CSlot::isEnable()
    {
        return m_bEnable;
    }
    void CSlot::enable()
    {
        m_bEnable = TRUE;
    }
    void CSlot::disable()
    {
        m_bEnable = FALSE;
    }
    BOOL CSlot::isLock()
    {
        return m_bLock;
    }
    void CSlot::lock()
    {
        m_bLock = TRUE;
    }
    void CSlot::unlock()
    {
        m_bLock = FALSE;
    }
    int CSlot::getPosition()
    {
        return m_nPosition;
    }
    void CSlot::setPosition(int position)
    {
        m_nPosition = position;
    }
    int CSlot::getNo()
    {
        return m_nNo;
    }
    void CSlot::setNo(int no)
    {
        m_nNo = no;
    }
    MaterialsType CSlot::getType()
    {
        return m_materialsType;
    }
    void CSlot::setType(MaterialsType type)
    {
        m_materialsType = type;
    }
    std::string& CSlot::getName()
    {
        return m_strName;
    }
    void CSlot::setName(const char* pszName)
    {
        m_strName = pszName;
    }
    BOOL CSlot::isEmpty()
    {
        return m_pContext == nullptr;
    }
    void CSlot::setContext(CContext* pContext)
    {
        if (pContext != nullptr) {
            pContext->release();
        }
        m_pContext = pContext;
        if (m_pContext != nullptr) {
            m_pContext->addRef();
        }
    }
    CContext* CSlot::getContext()
    {
        return m_pContext;
    }
    void CSlot::serialize(CArchive& ar)
    {
        if (ar.IsStoring()) {
            ar << m_nPosition;
            ar << m_nNo;
            ar << (int)m_materialsType;
            WriteString(ar, m_strName);
            ar << (__int64)m_pContext;
            ar << m_bEnable;
            ar << m_bLock;
        }
        else {
            int i32;
            __int64 i64;
            ar >> m_nPosition;
            ar >> m_nNo;
            ar >> i32; m_materialsType = (MaterialsType)i32;
            ReadString(ar, m_strName);
            ar >> i64; m_pContext = (CContext*)i64;
            ar >> m_bEnable;
            ar >> m_bLock;
        }
    }
    void CSlot::WriteString(CArchive& ar, std::string& string)
    {
        CString strTemp = string.c_str();
        ar << strTemp;
    }
    void CSlot::ReadString(CArchive& ar, std::string& string)
    {
        CString strTemp;
        ar >> strTemp;
        string = (LPTSTR)(LPCTSTR)strTemp;
    }
}
SourceCode/Bond/Servo/CSlot.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
#pragma once
#include "Context.h"
#include "ServoCommo.h"
namespace SERVO {
    class CSlot
    {
    public:
        CSlot();
        virtual ~CSlot();
    public:
        BOOL isEnable();
        void enable();
        void disable();
        BOOL isLock();
        void lock();
        void unlock();
        int getPosition();
        void setPosition(int position);
        int getNo();
        void setNo(int no);
        MaterialsType getType();
        void setType(MaterialsType type);
        std::string& getName();
        void setName(const char* pszName);
        BOOL isEmpty();
        CContext* getContext();
        void setContext(CContext* pContext);
        void serialize(CArchive& ar);
    private:
        void WriteString(CArchive& ar, std::string& string);
        void ReadString(CArchive& ar, std::string& string);
    private:
        int m_nPosition;
        int m_nNo;
        MaterialsType m_materialsType;
        std::string m_strName;
        CContext* m_pContext;
        BOOL m_bEnable;
        BOOL m_bLock;
    };
}
SourceCode/Bond/Servo/CVacuumBake.cpp
@@ -38,6 +38,16 @@
        addPin(SERVO::PinType::OUTPUT, _T("Out"));
    }
    // å¿…须要实现的虚函数,在此初始化Slot信息
    void CVacuumBake::initSlots()
    {
        m_slot[0].enable();
        m_slot[0].setPosition(m_nID);
        m_slot[0].setNo(1);
        m_slot[0].setName("Slot 1(G1)");
        m_slot[0].setType(MaterialsType::G1);
    }
    void CVacuumBake::onTimer(UINT nTimerid)
    {
        CEquipment::onTimer(nTimerid);
@@ -56,41 +66,6 @@
    int CVacuumBake::recvIntent(CPin* pPin, CIntent* pIntent)
    {
        return __super::recvIntent(pPin, pIntent);
    }
    BOOL CVacuumBake::glassWillArrive(CGlass* pGlass)
    {
        BOOL bRet = __super::glassWillArrive(pGlass);
        if (!bRet) {
            return FALSE;
        }
        return m_glassList.empty();
    }
    BOOL CVacuumBake::onPreStoredJob(int port, CJobDataB* pJobDataB)
    {
        CJobDataS* pJobDataS = getJobDataS(pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
        if (pJobDataS == nullptr) {
            LOGE("<CVacuumBake-%s>onPreFetchedOutJob,找不到对应的JobDataS(CassetteSequenceNo:%d, JobSequenceNo:%d), æ³¨æ„æŽ’查风险!", m_strName.c_str(),
                pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo());
            return FALSE;
        }
        // å½“前不能有任何玻璃,且当前准备进的片是G1
        Lock();
        if (!m_glassList.empty()) {
            Unlock();
            LOGE("<CVacuumBake-%s>onPreFetchedOutJob,当前机器或单元存在玻璃片,不能进料,请注意风险!", m_strName.c_str());
            return FALSE;
        }
        if (pJobDataS->getMaterialsType() != (int)MaterialsType::G1) {
            LOGE("<CVacuumBake-%s>onPreFetchedOutJob,当前机器或单元只能进G2玻璃片,请注意风险!", m_strName.c_str());
            return FALSE;
        }
        return TRUE;
    }
    int CVacuumBake::getIndexerOperationModeBaseValue()
SourceCode/Bond/Servo/CVacuumBake.h
@@ -15,12 +15,11 @@
        virtual void init();
        virtual void term();
        virtual void initPins();
        virtual void initSlots();
        virtual void onTimer(UINT nTimerid);
        virtual void serialize(CArchive& ar);
        virtual void getAttributeVector(CAttributeVector& attrubutes);
        virtual int recvIntent(CPin* pPin, CIntent* pIntent);
        virtual BOOL glassWillArrive(CGlass* pGlass);
        virtual BOOL onPreStoredJob(int port, CJobDataB* pJobDataB);
        virtual int getIndexerOperationModeBaseValue();
    };
SourceCode/Bond/Servo/CVcrEventReport.h
@@ -8,7 +8,7 @@
    {
    public:
        CVcrEventReport();
        ~CVcrEventReport();
        virtual ~CVcrEventReport();
    public:
        std::string& getGlassId();
SourceCode/Bond/Servo/Common.h
@@ -16,6 +16,7 @@
#define RX_CODE_ALARM_SET                1008
#define RX_CODE_ALARM_CLEAR                1009
#define RX_CODE_EQ_DATA_CHANGED            1010
#define RX_CODE_MASTER_STATE_CHANGED    1011
/* Channel Name */
@@ -37,7 +38,10 @@
#define CR_MSGBOX_BKGND                        RGB(7, 71, 166)
#define CR_MSGBOX_TITLE                        RGB(200, 216, 246)
#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_RUNNING                RGB(34, 177, 76)
#define STATUSBAR_BK_ALARM                    RGB(255, 127, 39)
/* LOG BTN */
#define BTN_LOG_FRAME_NORMAL            RGB(88, 88, 88)
@@ -56,22 +60,22 @@
#define BTN_ALARM_BKGND_PRESS            RGB(133, 203, 225)
/* Equipment ID */
#define EQ_ID_EFEM                1
#define EQ_ID_Bonder1            2
#define EQ_ID_Bonder2            3
#define EQ_ID_LOADPORT1            4
#define EQ_ID_LOADPORT2            5
#define EQ_ID_LOADPORT3            6
#define EQ_ID_LOADPORT4            7
#define EQ_ID_LOADPORT1            1
#define EQ_ID_LOADPORT2            2
#define EQ_ID_LOADPORT3            3
#define EQ_ID_LOADPORT4            4
#define EQ_ID_ARM_TRAY1            5
#define EQ_ID_ARM_TRAY2            6
#define EQ_ID_ALIGNER            7
#define EQ_ID_FLIPER            8
#define EQ_ID_VACUUMBAKE        9
#define EQ_ID_ALIGNER            10
#define EQ_ID_BAKE_COOLING        11
#define EQ_ID_MEASUREMENT        12
#define EQ_ID_ARM                13
#define EQ_ID_ARM_TRAY1            14
#define EQ_ID_ARM_TRAY2            15
#define EQ_ID_OPERATOR_REMOVE    999
#define EQ_ID_Bonder1            10
#define EQ_ID_Bonder2            11
#define EQ_ID_BAKE_COOLING        12
#define EQ_ID_MEASUREMENT        13
#define EQ_ID_EFEM                100
#define EQ_ID_ARM                101
#define EQ_ID_OPERATOR_REMOVE    102
/* step name */
@@ -405,12 +409,7 @@
/* æµç¨‹æŽ§åˆ¶ç›¸å…³ä»£ç  */
#define FLOW_REJECT                    0x0
#define FLOW_ACCEPT                    0x1
#define FLOW_TEST                    0x1000
#define FLOW_SIGNAL                    0x1001
#define FLOW_DATA                    0x1002
#define FLOW_MOVE_MATERIAL            0x1003
/* Port Status */
SourceCode/Bond/Servo/Model.cpp
@@ -29,6 +29,11 @@
    return m_pObservable;
}
SERVO::CMaster& CModel::getMaster()
{
    return m_master;
}
void CModel::setWorkDir(const char* pszWorkDir)
{
    m_strWorkDir = pszWorkDir;
@@ -98,6 +103,10 @@
    SERVO::MasterListener masterListener;
    masterListener.onMasterStateChanged = [&](void* pMaster, SERVO::MASTERSTATE state) -> void {
        LOGI("<CModel>Master state changed(%d)", (int)state);
        notify(RX_CODE_MASTER_STATE_CHANGED);
    };
    masterListener.onEqAlive = [&](void* pMaster, SERVO::CEquipment* pEquipment, BOOL bAlive) -> void {
        LOGI("<CModel>Equipment onAlive:%s(%s).\n", pEquipment->getName().c_str(),
            bAlive ? _T("ON") : _T("OFF"));
SourceCode/Bond/Servo/Model.h
@@ -12,6 +12,7 @@
public:
    IObservable* getObservable();
    SERVO::CMaster& getMaster();
    void setWorkDir(const char* pszWorkDir);
    int init();
    int term();
SourceCode/Bond/Servo/Servo.cpp
@@ -10,6 +10,7 @@
#include "SECSRuntimeManager.h"
#include "TransferManager.h"
#include "VerticalLine.h"
#include "HorizontalLine.h"
#include "EqsGraphWnd.h"
#include "MapPosWnd.h"
#include "HmTab.h"
@@ -99,6 +100,7 @@
    // æ³¨å†ŒæŽ§ä»¶
    CServoGraph::RegisterWndClass();
    CVerticalLine::RegisterWndClass();
    CHorizontalLine::RegisterWndClass();
    CEqsGraphWnd::RegisterWndClass();
    CMapPosWnd::RegisterWndClass();
    CHmTab::RegisterWndClass();
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/Servo.vcxproj
@@ -200,6 +200,7 @@
  <ItemGroup>
    <ClInclude Include="CEquipmentPage3.h" />
    <ClInclude Include="CGlassPool.h" />
    <ClInclude Include="CMyStatusbar.h" />
    <ClInclude Include="CRobotCmdContainerDlg.h" />
    <ClInclude Include="CRobotCmdTestDlg.h" />
    <ClInclude Include="CPagePortStatus.h" />
@@ -218,6 +219,9 @@
    <ClInclude Include="GridControl\NewCellTypes\GridCellNumeric.h" />
    <ClInclude Include="GridControl\NewCellTypes\GridURLCell.h" />
    <ClInclude Include="GridControl\TitleTip.h" />
    <ClInclude Include="CRobotTask.h" />
    <ClInclude Include="CSlot.h" />
    <ClInclude Include="HorizontalLine.h" />
    <ClInclude Include="JobSlotGrid.h" />
    <ClInclude Include="MsgDlg.h" />
    <ClInclude Include="PageRecipe.h" />
@@ -318,11 +322,13 @@
    <ClInclude Include="TerminalDisplayDlg.h" />
    <ClInclude Include="ToolUnits.h" />
    <ClInclude Include="TransferManager.h" />
    <ClInclude Include="TopToolbar.h" />
    <ClInclude Include="VerticalLine.h" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="CEquipmentPage3.cpp" />
    <ClCompile Include="CGlassPool.cpp" />
    <ClCompile Include="CMyStatusbar.cpp" />
    <ClCompile Include="CRobotCmdContainerDlg.cpp" />
    <ClCompile Include="CRobotCmdTestDlg.cpp" />
    <ClCompile Include="CPagePortStatus.cpp" />
@@ -339,6 +345,9 @@
    <ClCompile Include="GridControl\NewCellTypes\GridCellNumeric.cpp" />
    <ClCompile Include="GridControl\NewCellTypes\GridURLCell.cpp" />
    <ClCompile Include="GridControl\TitleTip.cpp" />
    <ClCompile Include="CRobotTask.cpp" />
    <ClCompile Include="CSlot.cpp" />
    <ClCompile Include="HorizontalLine.cpp" />
    <ClCompile Include="JobSlotGrid.cpp" />
    <ClCompile Include="MsgDlg.cpp" />
    <ClCompile Include="PageRecipe.cpp" />
@@ -440,6 +449,7 @@
    <ClCompile Include="TerminalDisplayDlg.cpp" />
    <ClCompile Include="ToolUnits.cpp" />
    <ClCompile Include="TransferManager.cpp" />
    <ClCompile Include="TopToolbar.cpp" />
    <ClCompile Include="VerticalLine.cpp" />
  </ItemGroup>
  <ItemGroup>
SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -150,6 +150,11 @@
    </ClCompile>
    <ClCompile Include="PortConfigurationDlg.cpp" />
    <ClCompile Include="TransferManager.cpp" />
    <ClCompile Include="TopToolbar.cpp" />
    <ClCompile Include="HorizontalLine.cpp" />
    <ClCompile Include="CMyStatusbar.cpp" />
    <ClCompile Include="CRobotTask.cpp" />
    <ClCompile Include="CSlot.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AlarmManager.h" />
@@ -305,6 +310,11 @@
    </ClInclude>
    <ClInclude Include="PortConfigurationDlg.h" />
    <ClInclude Include="TransferManager.h" />
    <ClInclude Include="TopToolbar.h" />
    <ClInclude Include="HorizontalLine.h" />
    <ClInclude Include="CMyStatusbar.h" />
    <ClInclude Include="CRobotTask.h" />
    <ClInclude Include="CSlot.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Servo.rc" />
SourceCode/Bond/Servo/ServoCommo.h
@@ -2,7 +2,12 @@
namespace SERVO {
    enum PortType {
#define BLOCK_BUFFER_MAX            1024
#define ALIVE_TIMEOUT                15
#define VCR_MAX                        1
#define ARM_ALL                        99
    enum class PortType {
        Loading = 1,
        Unloading,
        Both,
@@ -12,7 +17,7 @@
        UnloadingPartial
    };
    enum PortMode {
    enum class PortMode {
        OutOfService = 0,
        TransferBlocked,
        ReadyToLoad,
@@ -21,17 +26,95 @@
        TransferReady
    };
    enum MaterialsType {
        G1 = 0,
        G2 = 1,
        G1G2 = 2
    enum class MaterialsType {
        G1 = 1,
        G2 = 2,
        G1G2 = 3
    };
    typedef MaterialsType CassetteType;
    enum TransferMode {
    enum class TransferMode {
        MGVMode = 1,
        AGVMode,
        StockerInlineMode
    };
    // Memory Block ç»“构体定义
    typedef struct _MemoryBlock {
        unsigned int type;
        unsigned int start;
        unsigned int end;
        unsigned int size;
        char buffer[BLOCK_BUFFER_MAX];
    } MemoryBlock;
    // ALIVE
    typedef struct _ALIVE {
        BOOL flag;
        int count;
        BOOL alive;
    } ALIVE;
    enum class DISPATCHING_MODE {
        EAS = 1,
        Local = 2
    };
    enum class IDNEXER_OPERATION_MODE {
        Normal = 1,
        Clear_Out = 2,
        Cold_Run = 2,
        Start = 10,
        Stop = 11,
        Pause = 12,
        Resume = 13,
        Abort = 14,
        Cancel = 15,
    };
    enum class VCR_Reply_Code {
        OK = 1,
        NG,
        Job_Data_Request,
        VCR_Mismatch
    };
    // Robot cmd param
#define ROBOT_CMD_PARAM_SIZE        16            /* é˜²æ­¢ä»¥åŽä¿®æ”¹ROBOT_CMD_PARAM为不是4的整数倍 */
    typedef struct _ROBOT_CMD_PARAM {
        short sequenceNo;
        short rcmd;
        short armNo;
        short getPosition;
        short putPosition;
        short getSlotNo;
        short putSlotNo;
        short subCmd;
    } ROBOT_CMD_PARAM;
    enum class RCMD {
        Robot_home = 1,
        Transfer,
        Move,
        Get,
        Put,
        One_Action_Exchange,
        Two_Action_Exchange,
        Command_Clear,
        Batch_get,
        Batch_put
    };
    enum class ROBOT_TASK_STATE {
        Ready = 0,
        Running,
        Error,
        Abort,
        Completed
    };
    /* EQ Data changed code */
#define EDCC_FETCHOUT_JOB                1000    /* È¡Æ¬ */
#define EDCC_STORED_JOB                    1001    /* æ”¾ç‰‡ */
}
SourceCode/Bond/Servo/ServoDlg.cpp
@@ -13,6 +13,8 @@
#include <thread>
#include <cmath>
#include "HmTab.h"
#include "CRobotCmdContainerDlg.h"
#include "CRobotCmdTestDlg.h"
#ifdef _DEBUG
@@ -22,6 +24,10 @@
/* åˆ›å»ºç»ˆç«¯çš„定时器 */
#define TIMER_ID_CREATE_TERMINAL        1
/* è¿è¡Œæ—¶é—´å®šæ—¶å™¨ */
#define TIMER_ID_UPDATE_RUMTIME            2
// ç”¨äºŽåº”用程序“关于”菜单项的 CAboutDlg å¯¹è¯æ¡†
@@ -76,6 +82,8 @@
    m_pPageAlarm = nullptr;
    m_pPageLog = nullptr;
    m_pPageRecipe = nullptr;
    m_pTopToolbar = nullptr;
    m_pMyStatusbar = nullptr;
}
void CServoDlg::DoDataExchange(CDataExchange* pDX)
@@ -110,6 +118,7 @@
    ON_WM_TIMER()
    ON_MESSAGE(ID_MSG_PANEL_RESIZE, OnPanelResize)
    ON_NOTIFY(BYHMTAB_SEL_CHANGED, IDC_TAB1, &CServoDlg::OnTabSelChanged)
    ON_MESSAGE(ID_MSG_TOOLBAR_BTN_CLICKED, &CServoDlg::OnToolbarBtnClicked)
END_MESSAGE_MAP()
@@ -158,6 +167,22 @@
                        m_pPanelAttributes->ShowWindow(SW_SHOW);
                        Resize();
                    }
                }
            }
            else if (RX_CODE_MASTER_STATE_CHANGED == code) {
                SERVO::MASTERSTATE state = theApp.m_model.getMaster().getState();
                if (state == SERVO::MASTERSTATE::READY) {
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_NORMAL);
                    m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
                    KillTimer(TIMER_ID_UPDATE_RUMTIME);
                    CString strText;
                    GetRuntimeFormatText(strText, "");
                    m_pMyStatusbar->setRunTimeText((LPTSTR)(LPCTSTR)strText);
                }
                else if (state == SERVO::MASTERSTATE::RUNNING) {
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_RUNNING);
                    m_pMyStatusbar->setForegroundColor(RGB(255, 255, 255));
                    SetTimer(TIMER_ID_UPDATE_RUMTIME, 500, nullptr);
                }
            }
@@ -210,6 +235,17 @@
    SetMenu(&menu);
    // toolbar
    m_pTopToolbar = new CTopToolbar();
    m_pTopToolbar->Create(IDD_TOP_TOOLBAR, this);
    m_pTopToolbar->ShowWindow(SW_SHOW);
    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
    m_pTopToolbar->GetBtn(IDC_BUTTON_ALARM)->EnableWindow(FALSE);
    HMENU hMenu = m_pTopToolbar->GetOperatorMenu();
    ASSERT(hMenu);
    ::EnableMenuItem(hMenu, ID_OPEATOR_SWITCH, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
    // Tab
    m_pPageGraph1 = new CPageGraph1();
    m_pPageGraph1->Create(IDD_PAGE_GRAPH1, this);
@@ -242,6 +278,13 @@
    m_pPanelEquipment->Create(IDD_PANEL_EQUIPMENT, this);
    m_pPanelAttributes = new CPanelAttributes();
    m_pPanelAttributes->Create(IDD_PANEL_ATTRIBUTES, this);
    // statusbar
    m_pMyStatusbar = new CMyStatusbar();
    m_pMyStatusbar->Create(IDD_STATUSBAR, this);
    m_pMyStatusbar->ShowWindow(SW_SHOW);
    
    // è°ƒæ•´åˆå§‹çª—口位置
@@ -491,6 +534,18 @@
    CDialogEx::OnDestroy();
    if (m_pTopToolbar != nullptr) {
        m_pTopToolbar->DestroyWindow();
        delete m_pTopToolbar;
        m_pTopToolbar = nullptr;
    }
    if (m_pMyStatusbar != nullptr) {
        m_pMyStatusbar->DestroyWindow();
        delete m_pMyStatusbar;
        m_pMyStatusbar = nullptr;
    }
    if (m_pTerminalDisplayDlg != nullptr) {
        m_pTerminalDisplayDlg->DestroyWindow();
        delete m_pTerminalDisplayDlg;
@@ -570,31 +625,40 @@
    Invalidate();
}
#define TOOLBAR_HEIGHT        78
#define STATUSBAR_HEIGHT    38
void CServoDlg::Resize()
{
    CRect rcClient, rcItem;
    CWnd* pItem = nullptr;
    int x, y;
    int x, y, y2;
    GetClientRect(&rcClient);
    x = 0;
    y = 0;
    y2 = rcClient.bottom - STATUSBAR_HEIGHT;
    m_pTopToolbar->MoveWindow(0, 0, rcClient.Width(), TOOLBAR_HEIGHT);
    y += TOOLBAR_HEIGHT;
    int nPanelWidth = 0;
    if (m_pPanelMaster != nullptr) {
        nPanelWidth = m_pPanelMaster->getPanelWidth();
        m_pPanelMaster->MoveWindow(x, y, nPanelWidth, rcClient.Height());
        m_pPanelMaster->MoveWindow(x, y, nPanelWidth, y2 - y);
        x += nPanelWidth;
    }
    if (m_pPanelEquipment != nullptr && m_pPanelEquipment->IsWindowVisible()) {
        nPanelWidth = m_pPanelEquipment->getPanelWidth();
        m_pPanelEquipment->MoveWindow(x, y, nPanelWidth, rcClient.Height());
        m_pPanelEquipment->MoveWindow(x, y, nPanelWidth, y2 - y);
        x += nPanelWidth;
    }
    if (m_pPanelAttributes != nullptr && m_pPanelAttributes->IsWindowVisible()) {
        nPanelWidth = m_pPanelAttributes->getPanelWidth();
        m_pPanelAttributes->MoveWindow(x, y, nPanelWidth, rcClient.Height());
        m_pPanelAttributes->MoveWindow(x, y, nPanelWidth, y2 - y);
        x += nPanelWidth;
    }
@@ -605,11 +669,14 @@
    y += rcItem.Height();
    m_pPageGraph1->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
    m_pPageGraph2->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
    m_pPageRecipe->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
    m_pPageAlarm->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
    m_pPageLog->MoveWindow(x, y, rcClient.Width() - x, rcClient.Height() - y);
    m_pPageGraph1->MoveWindow(x, y, rcClient.Width() - x, y2 - y);
    m_pPageGraph2->MoveWindow(x, y, rcClient.Width() - x, y2 - y);
    m_pPageRecipe->MoveWindow(x, y, rcClient.Width() - x, y2 - y);
    m_pPageAlarm->MoveWindow(x, y, rcClient.Width() - x, y2 - y);
    m_pPageLog->MoveWindow(x, y, rcClient.Width() - x, y2 - y);
    m_pMyStatusbar->MoveWindow(0, y2, rcClient.Width(), STATUSBAR_HEIGHT);
}
void CServoDlg::OnClose()
@@ -648,6 +715,17 @@
        m_pTerminalDisplayDlg->Create(IDD_DIALOG_TERMINAL_DISPLAY, this);
    }
    if (TIMER_ID_UPDATE_RUMTIME == nIDEvent) {
        static int index = 0; index++;
        if (index >= 4) index = 0;
        static char* status[] = {"|", "/", "--", "\\"};
        CString strText;
        GetRuntimeFormatText(strText, status[index]);
        m_pMyStatusbar->setRunTimeText((LPTSTR)(LPCTSTR)strText);
    }
    CDialogEx::OnTimer(nIDEvent);
}
@@ -676,3 +754,44 @@
        pPages[i]->ShowWindow(i == index ? SW_SHOW : SW_HIDE);
    }
}
LRESULT CServoDlg::OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam)
{
    int id = (int)lParam;
    if (id == IDC_BUTTON_RUN) {
        theApp.m_model.getMaster().start();
        m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
        m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(TRUE);
    }
    else if (id == IDC_BUTTON_STOP) {
        theApp.m_model.getMaster().stop();
        m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
        m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
    }
    else if (id == IDC_BUTTON_ROBOT) {
        SERVO::CEFEM* pEFEM = (SERVO::CEFEM*)theApp.m_model.getMaster().getEquipment(EQ_ID_EFEM);
        CRobotCmdTestDlg dlg;
        dlg.SetEFEM(pEFEM);
        dlg.DoModal();
    }
    return 0;
}
CString& CServoDlg::GetRuntimeFormatText(CString& strText, const char* pszSuffix)
{
    ULONGLONG ullRunTime = (ULONGLONG)(theApp.m_model.getMaster().getRunTime() * 0.001);
    int h, m, s;
    h = int(ullRunTime / 3600);
    m = int((ullRunTime % 3600) / 60);
    s = int(ullRunTime % 60);
    SERVO::MASTERSTATE state = theApp.m_model.getMaster().getState();
    if (state == SERVO::MASTERSTATE::RUNNING) {
        strText.Format(_T("正在运行:%02d:%02d:%02d   %s"), h, m, s, pszSuffix);
    }
    else {
        strText.Format(_T("已运行:%02d:%02d:%02d   %s"), h, m, s, pszSuffix);
    }
    return strText;
}
SourceCode/Bond/Servo/ServoDlg.h
@@ -13,6 +13,8 @@
#include "CPanelAttributes.h"
#include "CPageGraph1.h"
#include "CPageGraph2.h"
#include "TopToolbar.h"
#include "CMyStatusbar.h"
// CServoDlg å¯¹è¯æ¡†
@@ -30,7 +32,7 @@
    void InitRxWindows();
    void Resize();
    void ShowChildPage(int index);
    CString& GetRuntimeFormatText(CString& strText, const char* pszSuffix);
private:
    IObserver* m_pObserver;
@@ -56,9 +58,11 @@
    HICON m_hIcon;
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
    CTopToolbar* m_pTopToolbar;
    CPanelMaster* m_pPanelMaster;
    CPanelEquipment* m_pPanelEquipment;
    CPanelAttributes* m_pPanelAttributes;
    CMyStatusbar* m_pMyStatusbar;
    // ç”Ÿæˆçš„æ¶ˆæ¯æ˜ å°„函数
    virtual BOOL OnInitDialog();
@@ -90,4 +94,5 @@
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg LRESULT OnPanelResize(WPARAM wParam, LPARAM lParam);
    afx_msg void OnTabSelChanged(NMHDR* nmhdr, LRESULT* result);
    LRESULT OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam);
};
SourceCode/Bond/Servo/ToolUnits.cpp
@@ -75,9 +75,8 @@
ULONGLONG CToolUnits::getTimestamp()
{
    auto now = std::chrono::system_clock::now();
    auto duration_in_milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
    uint64_t timestamp = duration_in_milliseconds.count();
    return timestamp;
    auto ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
    return static_cast<ULONGLONG>(ms.time_since_epoch().count());
}
void CToolUnits::createDir(const char* pszDir)
SourceCode/Bond/Servo/TopToolbar.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,218 @@
// TopToolbar.cpp : å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "Servo.h"
#include "TopToolbar.h"
#include "afxdialogex.h"
#include "Common.h"
// CTopToolbar å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CTopToolbar, CDialogEx)
CTopToolbar::CTopToolbar(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_TOP_TOOLBAR, pParent)
{
    m_crBkgnd = TOP_TOOLBAR_BACKGROUND;
    m_hbrBkgnd = nullptr;
}
CTopToolbar::~CTopToolbar()
{
}
void CTopToolbar::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_BUTTON_RUN, m_btnRun);
    DDX_Control(pDX, IDC_BUTTON_STOP, m_btnStop);
    DDX_Control(pDX, IDC_BUTTON_ALARM, m_btnAlarm);
    DDX_Control(pDX, IDC_BUTTON_SETTINGS, m_btnSettings);
    DDX_Control(pDX, IDC_BUTTON_ROBOT, m_btnRobot);
    DDX_Control(pDX, IDC_BUTTON_OPERATOR, m_btnOperator);
}
BEGIN_MESSAGE_MAP(CTopToolbar, CDialogEx)
    ON_WM_CTLCOLOR()
    ON_WM_DESTROY()
    ON_WM_SIZE()
    ON_NOTIFY(BLBUTTON_MENU_ITEM_CLICKED, IDC_BUTTON_OPERATOR, &CTopToolbar::OnButtonOperatorMenuClicked)
END_MESSAGE_MAP()
// CTopToolbar æ¶ˆæ¯å¤„理程序
BOOL CTopToolbar::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    InitBtn(m_btnRun, "Run_High_32.ico", "Run_Gray_32.ico");
    InitBtn(m_btnStop, "Stop_High_32.ico", "Stop_Gray_32.ico");
    InitBtn(m_btnAlarm, "Alarm_o_32.ico", "Alarm_gray_32.ico");
    InitBtn(m_btnSettings, "Settings_High_32.ico", "Settings_Gray_32.ico");
    InitBtn(m_btnRobot, "Robot_High_32.ico", "Robot_Gray_32.ico");
    InitBtn(m_btnOperator, "Operator_High_32.ico", "Operator_Gray_32.ico");
    HMENU hMenu = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCEA(IDR_MENU_OPEATOR));
    m_btnOperator.SetMenu(hMenu);
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
HBRUSH CTopToolbar::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    if (nCtlColor == CTLCOLOR_STATIC) {
        pDC->SetBkColor(m_crBkgnd);
    }
    if (m_hbrBkgnd == nullptr) {
        m_hbrBkgnd = CreateSolidBrush(m_crBkgnd);
    }
    return m_hbrBkgnd;
}
void CTopToolbar::OnDestroy()
{
    CDialogEx::OnDestroy();
    if (m_hbrBkgnd != nullptr) {
        ::DeleteObject(m_hbrBkgnd);
        m_hbrBkgnd = nullptr;
    }
}
void CTopToolbar::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (GetDlgItem(IDC_BUTTON_RUN) == nullptr) return;
    Resize();
}
#define BTN_WIDTH        60
#define BTN_HEIGHT        30
void CTopToolbar::Resize()
{
    CWnd* pItem;
    CRect rcClient, rcItem;
    GetClientRect(&rcClient);
    int nBthHeight = (rcClient.Height() - 10);
    int x = 2, y = 3;
    pItem = GetDlgItem(IDC_BUTTON_RUN);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_BUTTON_STOP);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_BUTTON_ALARM);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_TOOLBAR_LINE1);
    pItem->MoveWindow(x, y + 6, 2, nBthHeight - 12);
    x += 4;
    pItem = GetDlgItem(IDC_BUTTON_SETTINGS);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_BUTTON_ROBOT);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    x = rcClient.right - 5 - BTN_WIDTH - 20;
    pItem = GetDlgItem(IDC_BUTTON_OPERATOR);
    pItem->MoveWindow(x, y, BTN_WIDTH + 20, nBthHeight);
    CWnd* pLine = GetDlgItem(IDC_LINE1);
    pLine->MoveWindow(0, rcClient.bottom - 2, rcClient.Width(), 2);
}
void CTopToolbar::InitBtn(CBlButton& btn, const char* pszIcon1, const char* pszIcon2)
{
    CString strIcon1, strIcon2;
    HICON hIcon1, hIcon2;
    strIcon1.Format(_T("%s\\Res\\%s"), theApp.m_strAppDir, pszIcon1);
    strIcon2.Format(_T("%s\\Res\\%s"), theApp.m_strAppDir, pszIcon2);
    hIcon1 = (HICON)::LoadImage(AfxGetInstanceHandle(),
        strIcon1, IMAGE_ICON, 32, 32,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    hIcon2 = (HICON)::LoadImage(AfxGetInstanceHandle(),
        strIcon2, IMAGE_ICON, 32, 32,
        LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
    btn.SetBkgndColor(BS_NORMAL, TOP_TOOLBAR_BACKGROUND);
    btn.SetBkgndColor(BS_PRESS, RGB(185, 209, 234));
    btn.SetBkgndColor(BS_DISABLE, TOP_TOOLBAR_BACKGROUND);
    btn.SetFrameColor(BS_NORMAL, TOP_TOOLBAR_BACKGROUND);
    btn.SetFrameColor(BS_PRESS, RGB(185, 209, 234));
    btn.SetFrameColor(BS_HOVER, RGB(185, 209, 234));
    btn.SetFrameColor(BS_DISABLE, TOP_TOOLBAR_BACKGROUND);
    btn.SetIcon(hIcon1, hIcon2, 32);
}
CWnd* CTopToolbar::GetBtn(UINT nId)
{
    return GetDlgItem(nId);
}
void CTopToolbar::SetOperatorBtnText(const char* pszText)
{
    m_btnOperator.SetWindowText(pszText);
}
BOOL CTopToolbar::OnCommand(WPARAM wParam, LPARAM lParam)
{
    switch (LOWORD(wParam)) {
    case IDC_BUTTON_RUN:
    case IDC_BUTTON_STOP:
    case IDC_BUTTON_ALARM:
    case IDC_BUTTON_SETTINGS:
    case IDC_BUTTON_ROBOT:
        GetParent()->SendMessage(ID_MSG_TOOLBAR_BTN_CLICKED, 0, LOWORD(wParam));
        break;
    }
    return CDialogEx::OnCommand(wParam, lParam);
}
void CTopToolbar::OnButtonOperatorMenuClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
    BLBUTTON_NMHDR* pblbNmhdr = reinterpret_cast<BLBUTTON_NMHDR*>(pNMHDR);
    GetParent()->SendMessage(ID_MSG_TOOLBAR_BTN_CLICKED, (int)pblbNmhdr->dwData, IDC_BUTTON_OPERATOR);
    *pResult = 0;
}
HMENU CTopToolbar::GetOperatorMenu()
{
    return m_btnOperator.GetMenu();
}
BOOL CTopToolbar::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) {
        return TRUE;
    }
    return CDialogEx::PreTranslateMessage(pMsg);
}
SourceCode/Bond/Servo/TopToolbar.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
#pragma once
#include "BlButton.h"
#define ID_MSG_TOOLBAR_BTN_CLICKED        WM_USER + 20368
// CTopToolbar å¯¹è¯æ¡†
class CTopToolbar : public CDialogEx
{
    DECLARE_DYNAMIC(CTopToolbar)
public:
    CTopToolbar(CWnd* pParent = NULL);   // æ ‡å‡†æž„造函数
    virtual ~CTopToolbar();
public:
    CWnd* GetBtn(UINT nId);
    void SetOperatorBtnText(const char* pszText);
    HMENU GetOperatorMenu();
private:
    void Resize();
    void InitBtn(CBlButton& btn, const char* pszIcon1, const char* pszIcon2);
private:
    COLORREF m_crBkgnd;
    HBRUSH m_hbrBkgnd;
private:
    CBlButton m_btnRun;
    CBlButton m_btnStop;
    CBlButton m_btnAlarm;
    CBlButton m_btnSettings;
    CBlButton m_btnRobot;
    CBlButton m_btnOperator;
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_TOP_TOOLBAR };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg void OnDestroy();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
    afx_msg void OnButtonOperatorMenuClicked(NMHDR* pNMHDR, LRESULT* pResult);
    virtual BOOL PreTranslateMessage(MSG* pMsg);
};
SourceCode/Bond/Servo/resource.h
Binary files differ
SourceCode/Bond/x64/Debug/Master.dat
Binary files differ
SourceCode/Bond/x64/Debug/Res/robot_Gray_32.ico
SourceCode/Bond/x64/Debug/Res/robot_High_32.ico