已修改12个文件
457 ■■■■■ 文件已修改
SourceCode/Bond/Servo/CEquipment.cpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp 381 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.h 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Configuration.cpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Configuration.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Model.cpp 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.cpp 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/TopToolbar.cpp 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/TopToolbar.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.cpp
@@ -1325,7 +1325,7 @@
        return nullptr;
    }
    CSlot* CEquipment::getProcessedSlot(MaterialsType putSlotType)
    CSlot* CEquipment::getProcessedSlot(MaterialsType putSlotType, BOOL bJobMode/* = FALSE*/)
    {
        for (int i = 0; i < SLOT_MAX; i++) {
            if (!m_slot[i].isEnable()) continue;
@@ -1334,6 +1334,7 @@
            if (!isSlotProcessed(i)) continue;
            if (pGlass == nullptr) continue;
            if (!pGlass->isScheduledForProcessing()) continue;
            if (bJobMode && pGlass->getProcessJob() == nullptr) continue;
            if(pGlass->getInspResult(m_nID, 0) == InspResult::Fail) continue;
            int lsPath = m_slot[i].getLinkSignalPath();
            if(!m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_INLINE]
@@ -1654,7 +1655,7 @@
    int CEquipment::decodeVCREventReport(CStep* pStep, const char* pszData, size_t size)
    {
        CVcrEventReport vcrEventReport;
        vcrEventReport.unserialize(pszData, size);
        vcrEventReport.unserialize(pszData, (int)size);
        LOGI("<CEquipment-%s>decodeVCREventReport<Result:%d, GlassId:%s>\n", m_strName.c_str(),
            vcrEventReport.getVcrResult(),
            vcrEventReport.getGlassId().c_str());
SourceCode/Bond/Servo/CEquipment.h
@@ -185,7 +185,7 @@
        CSlot* getNonEmptySlot(MaterialsType type);
        // 获取一个指定物料类型(G1,G2,G1&G2)的且已经加工处理的槽位
        CSlot* getProcessedSlot(MaterialsType putSlotType);
        CSlot* getProcessedSlot(MaterialsType putSlotType, BOOL bJobMode = FALSE);
        CSlot* getProcessedSlot2(MaterialsType putSlotType, const std::vector<int>& candidates);
        CSlot* getInspFailSlot();
        CSlot* getProcessedSlotCt(unsigned int slot);
SourceCode/Bond/Servo/CMaster.cpp
@@ -55,9 +55,11 @@
        m_pActiveRobotTask = nullptr;
        m_nLastError = 0;
        m_isCompareMapsBeforeProceeding = FALSE;
        m_bJobMode = FALSE;
        m_bEnableEventReport = true;
        m_bEnableAlarmReport = true;
        m_bContinuousTransfer = false;
        m_bBatch = false;
        m_nContinuousTransferCount = 0;
        m_nContinuousTransferStep = CTStep_Unknow;
        m_pControlJob = nullptr;
@@ -269,6 +271,7 @@
        }
        m_bContinuousTransfer = false;
        m_bBatch = false;
        setState(MASTERSTATE::STARTING);
        m_ullStartTime = GetTickCount64();
@@ -282,6 +285,21 @@
        }
        m_bContinuousTransfer = true;
        m_bBatch = false;
        setState(MASTERSTATE::STARTING);
        m_ullStartTime = GetTickCount64();
        return 0;
    }
    int CMaster::startBatch()
    {
        if (m_state != MASTERSTATE::READY) {
            return -1;
        }
        m_bContinuousTransfer = false;
        m_bBatch = true;
        setState(MASTERSTATE::STARTING);
        m_ullStartTime = GetTickCount64();
@@ -291,12 +309,28 @@
    int CMaster::stop()
    {
        // 运行时间为累加结果,本次停止时刷新;
        if (m_state != MASTERSTATE::RUNNING && m_state != MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
        lock();
        if (m_state != MASTERSTATE::RUNNING && m_state != MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER
            && m_state != MASTERSTATE::RUNNING_BATCH) {
            unlock();
            return -1;
        }
        m_ullRunTime += (GetTickCount64() - m_ullStartTime);
        unlock();
        // 更新状态
        setState(MASTERSTATE::STOPPING);
        // ControlJob暂停
        lock();
        if (m_pControlJob != nullptr) {
            m_pControlJob->pause();
            saveState();
        }
        unlock();
        return 0;
    }
@@ -310,7 +344,8 @@
    ULONGLONG CMaster::getRunTime()
    {
        if (m_state == MASTERSTATE::RUNNING || m_state == MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER)
        if (m_state == MASTERSTATE::RUNNING || m_state == MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER
            || m_state == MASTERSTATE::RUNNING_BATCH)
            return m_ullRunTime + (GetTickCount64() - m_ullStartTime);
        else
            return m_ullRunTime;
@@ -470,18 +505,21 @@
                }
                
                // 检查看是否都已经切换到START状态
                /*
                if (!bIomcOk[6]) {
                    unlock();
                    setState(MASTERSTATE::MSERROR);
                    continue;
                }
                */
                unlock();
                if(!m_bContinuousTransfer)
                    setState(MASTERSTATE::RUNNING);
                else
                if(m_bContinuousTransfer)
                    setState(MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER);
                else if (m_bBatch)
                    setState(MASTERSTATE::RUNNING_BATCH);
                else
                    setState(MASTERSTATE::RUNNING);
                continue;
            }
@@ -684,7 +722,7 @@
                    if (!rmd.armState[0] && pLoadPorts[s]->isEnable()
                        && (pt == PortType::Loading || pt == PortType::Both)
                        && pLoadPorts[s]->getPortStatus() == PORT_INUSE) {
                        m_pActiveRobotTask = createTransferTask(pLoadPorts[s], pAligner, primaryType, secondaryType);
                        m_pActiveRobotTask = createTransferTask(pLoadPorts[s], pAligner, primaryType, secondaryType, m_bJobMode);
                        if (m_pActiveRobotTask != nullptr) {
                            pEFEM->setContext(m_pActiveRobotTask->getContext());
                            goto PORT_GET;
@@ -693,6 +731,226 @@
                }
PORT_GET:
                CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                unlock();
                continue;
            }
            // 批处理模式,最终以此为准,但先保留之前的单片模式
            else if (m_state == MASTERSTATE::RUNNING_BATCH) {
                // 首选检查有没有CControlJob, 状态等
                if (m_pControlJob == nullptr) {
                    unlock();
                    continue;
                }
                CJState state = m_pControlJob->state();
                if (state == CJState::Completed || state == CJState::Aborted || state == CJState::Failed) {
                    // ConrolJpb已完成
                    LOGI("<Master>ControlJob已经完成或失败中断");
                    unlock();
                    continue;
                }
                if (m_pControlJob->state() == CJState::NoState) {
                    LOGI("<Master>ControlJob已经进入列队");
                    m_pControlJob->queue();
                }
                if (m_pControlJob->state() == CJState::Queued) {
                    LOGI("<Master>ControlJob已经启动");
                    m_pControlJob->start();
                }
                if (m_pControlJob->state() == CJState::Paused) {
                    LOGI("<Master>ControlJob已经恢复运行");
                    m_pControlJob->resume();
                }
                // 如果当前未选择CProcessJob, 选择一个
                if (m_inProcesJobs.empty()) {
                    auto pj = acquireNextProcessJob();
                    if (pj != nullptr) {
                        m_inProcesJobs.push_back(pj);
                    }
                }
                if (m_inProcesJobs.empty()) {
                    LOGI("<Master>选择当前ProcessJob失败!");
                    unlock();
                    continue;
                }
                // 如果当前没有Glass, 选择
                if (m_queueGlasses.empty()) {
                    int nCount = acquireGlassToQueue();
                    LOGI("<Master>已加入 %d 块Glass到工艺列队!", nCount);
                }
                // 检测判断robot状态
                RMDATA& rmd = pEFEM->getRobotMonitoringData();
                if (rmd.status != ROBOT_STATUS::Idle && rmd.status != ROBOT_STATUS::Run) {
                    unlock();
                    continue;
                }
                if (m_pActiveRobotTask != nullptr) {
                    if (m_pActiveRobotTask->isPicked()) {
                        m_pActiveRobotTask->place();
                    }
                    unlock();
                    // 检测到当前有正在下午的任务,确保当前任务完成或中止后继续
                    // LOGI("检测到当前有正在下午的任务,确保当前任务完成或中止后继续...");
                    continue;
                }
                // 此处检测优先类型和次要类型(G1或G2)
                // 如果其中一Bonder有单个玻璃,优先取它的配对类型,否则无所谓了
                primaryType = MaterialsType::G1;
                secondaryType = MaterialsType::G2;
                if ((!pBonder1->canPlaceGlassInSlot(0) && !pBonder1->canPlaceGlassInSlot(1))
                    && (!pBonder2->canPlaceGlassInSlot(0) && !pBonder2->canPlaceGlassInSlot(1))) {
                    // 如果G1和G2都满了,那就看Aligner, 如果Aligner有玻璃为G1, 则取G2
                    CGlass* pGlass = pAligner->getGlassFromSlot(1);
                    if (pGlass != nullptr && pGlass->getType() == MaterialsType::G1) {
                        primaryType = MaterialsType::G2;
                        secondaryType = MaterialsType::G1;
                    }
                }
                else if ((pBonder1->canPlaceGlassInSlot(0) && !pBonder1->canPlaceGlassInSlot(1))
                    || (pBonder2->canPlaceGlassInSlot(0) && !pBonder2->canPlaceGlassInSlot(1))) {
                    primaryType = MaterialsType::G2;
                    secondaryType = MaterialsType::G1;
                }
                // Measurement -> LoadPort
                if (rmd.armState[0] || rmd.armState[1]) {
                    LOGI("Arm1 %s, Arm2 %s.", rmd.armState[0] ? _T("不可用") : _T("可用"),
                        rmd.armState[1] ? _T("不可用") : _T("可用"));
                }
                for (int s = 0; s < 4; s++) {
                    PortType pt = pLoadPorts[s]->getPortType();
                    if (!rmd.armState[0] && pLoadPorts[s]->isEnable()
                        && (pt == PortType::Unloading || pt == PortType::Both)
                        && pLoadPorts[s]->getPortStatus() == PORT_INUSE) {
                        m_pActiveRobotTask = createTransferTask(pMeasurement, pLoadPorts[s], primaryType, secondaryType);
                        if (m_pActiveRobotTask != nullptr) {
                            goto BATCH_PORT_PUT;
                        }
                    }
                }
            BATCH_PORT_PUT:
                CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                // Measurement NG -> LoadPort
                // NG回原位
                if (!rmd.armState[1]) {
                    m_pActiveRobotTask = createTransferTask_restore(pMeasurement, pLoadPorts);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // BakeCooling ->Measurement
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask_bakecooling_to_measurement(pBakeCooling, pMeasurement);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // BakeCooling内部
                // Bake -> Cooling
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask_bake_to_cooling(pBakeCooling);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // Bonder -> BakeCooling
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask_bonder_to_bakecooling(pBonder1, pBakeCooling);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask_bonder_to_bakecooling(pBonder2, pBakeCooling);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // Fliper(G2) -> Bonder
                auto pSrcSlot = pVacuumBake->getProcessedSlot(primaryType);
                if (pSrcSlot != nullptr && !rmd.armState[1] && !pBonder1->hasBondClass()) {
                    m_pActiveRobotTask = createTransferTask(pFliper, pBonder1, primaryType, secondaryType, 2);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                if (pSrcSlot != nullptr && !rmd.armState[1] && !pBonder2->hasBondClass()) {
                    m_pActiveRobotTask = createTransferTask(pFliper, pBonder2, primaryType, secondaryType, 2);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // VacuumBake(G1) -> Bonder
                if (!rmd.armState[0] && !pBonder1->hasBondClass()) {
                    m_pActiveRobotTask = createTransferTask(pVacuumBake, pBonder1, primaryType, secondaryType);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                if (!rmd.armState[0] && !pBonder2->hasBondClass()) {
                    m_pActiveRobotTask = createTransferTask(pVacuumBake, pBonder2, primaryType, secondaryType);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // Aligner -> Fliper(G2)
                // Aligner -> VacuumBake(G1)
                if (!rmd.armState[1]) {
                    m_pActiveRobotTask = createTransferTask(pAligner, pFliper, primaryType, secondaryType);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                if (!rmd.armState[0]) {
                    m_pActiveRobotTask = createTransferTask(pAligner, pVacuumBake, primaryType, secondaryType);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // Aligner -> LoadPort
                if (!rmd.armState[1]) {
                    m_pActiveRobotTask = createTransferTask_restore(pAligner, pLoadPorts);
                    CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
                }
                // LoadPort -> Aligner
                for (int s = 0; s < 4; s++) {
                    PortType pt = pLoadPorts[s]->getPortType();
                    if (!rmd.armState[0] && pLoadPorts[s]->isEnable()
                        && (pt == PortType::Loading || pt == PortType::Both)
                        && pLoadPorts[s]->getPortStatus() == PORT_INUSE) {
                        m_pActiveRobotTask = createTransferTask(pLoadPorts[s], pAligner, primaryType, secondaryType, m_bJobMode);
                        if (m_pActiveRobotTask != nullptr) {
                            pEFEM->setContext(m_pActiveRobotTask->getContext());
                            bool bMoved = glassFromQueueToInPorcess((CGlass*)m_pActiveRobotTask->getContext());
                            if (bMoved) {
                                LOGI("<Master>Glass(%s)从等待列队到工艺列队转移成功.",
                                    ((CGlass*)m_pActiveRobotTask->getContext())->getID().c_str());
                            }
                            else {
                                LOGE("<Master>Glass(%s)从等待列队到工艺列队转移失败.",
                                    ((CGlass*)m_pActiveRobotTask->getContext())->getID().c_str());
                            }
                            goto BATCH_PORT_GET;
                        }
                    }
                }
            BATCH_PORT_GET:
                CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask);
@@ -1102,6 +1360,21 @@
                    LOGI("放片完成...");
                    // 完成此条搬送任务,但要把数据和消息上抛应用层
                    // 如果是搬送回从AOI搬送回Port, 则glass工艺完成
                    if (m_pActiveRobotTask->getSrcPosition() == EQ_ID_MEASUREMENT) {
                        bool bMoved = glassFromInPorcessToComplete((CGlass*)m_pActiveRobotTask->getContext());
                        if (bMoved) {
                            LOGI("<Master>Glass(%s)从工艺列队到完成列队转移成功.",
                                ((CGlass*)m_pActiveRobotTask->getContext())->getID().c_str());
                        }
                        else {
                            LOGE("<Master>Glass(%s)从工艺列队到完成列队转移失败.",
                                ((CGlass*)m_pActiveRobotTask->getContext())->getID().c_str());
                        }
                    }
                    unlock();
@@ -1567,7 +1840,7 @@
    static int taskSeqNo = 0;
    CRobotTask* CMaster::createTransferTask(CEquipment* pSrcEq, CEquipment* pTarEq,
        MaterialsType primaryType/* = MaterialsType::G1*/, MaterialsType secondaryType/* = MaterialsType::G2*/,
        int armNo/* = 1*/)
        int armNo/* = 1*/, BOOL bJobMode/* = FALSE*/)
    {
        if (!pSrcEq->IsEnabled()) { 
            return nullptr;
@@ -1576,10 +1849,10 @@
        CRobotTask* pTask = nullptr;
        CSlot* pSrcSlot, * pTarSlot;
        pTarSlot = pTarEq->getAvailableSlotForGlass(primaryType);
        pSrcSlot = pSrcEq->getProcessedSlot(primaryType);
        pSrcSlot = pSrcEq->getProcessedSlot(primaryType, bJobMode);
        if (pSrcSlot == nullptr || nullptr == pTarSlot) {
            pTarSlot = pTarEq->getAvailableSlotForGlass(secondaryType);
            pSrcSlot = pSrcEq->getProcessedSlot(secondaryType);
            pSrcSlot = pSrcEq->getProcessedSlot(secondaryType, bJobMode);
        }
@@ -1819,6 +2092,11 @@
    void CMaster::setCompareMapsBeforeProceeding(BOOL bCompare)
    {
        m_isCompareMapsBeforeProceeding = bCompare;
    }
    void CMaster::setJobMode(BOOL bJobMode)
    {
        m_bJobMode = bJobMode;
    }
    void CMaster::datetimeSync(SYSTEMTIME& time)
@@ -2089,4 +2367,85 @@
        return true;
    }
    CProcessJob* CMaster::acquireNextProcessJob()
    {
        auto& pjs = m_pControlJob->getPjs();
        for (const auto pj : pjs) {
            if (pj->state() == PJState::Queued) {
                pj->start();
            }
            return pj;
        }
        return nullptr;
    }
    CGlass* CMaster::acquireNextGlass()
    {
        for (auto* pj : m_inProcesJobs) {
            // 遍历 PJ 的 carriers 和 slots
            for (auto& cs : pj->carriers()) {
                for (auto ctx : cs.contexts) {
                    CGlass* pGlass = (CGlass*)ctx;
                    if (pGlass->state() == GlsState::NoState) {
                        pGlass->queue();
                        return pGlass;
                    }
                }
            }
        }
        return nullptr; // 没有可加工的 Glass
    }
    int CMaster::acquireGlassToQueue()
    {
        int nCount = 0;
        for (auto* pj : m_inProcesJobs) {
            // 遍历 PJ 的 carriers 和 slots
            for (auto& cs : pj->carriers()) {
                for (auto ctx : cs.contexts) {
                    CGlass* pGlass = (CGlass*)ctx;
                    if (pGlass->state() == GlsState::NoState) {
                        pGlass->queue();
                        if(addGlassToQueue(pGlass)) nCount++;
                    }
                }
            }
        }
        return nCount;
    }
    bool CMaster::addGlassToQueue(CGlass* pGlass)
    {
        for (auto g : m_queueGlasses) {
            if (g == pGlass) return false;
        }
        m_queueGlasses.push_back(pGlass);
        return true;
    }
    bool CMaster::glassFromQueueToInPorcess(CGlass* pGlass)
    {
        auto it = std::find(m_queueGlasses.begin(), m_queueGlasses.end(), pGlass);
        if (it != m_queueGlasses.end()) {
            m_inProcesGlasses.push_back(*it);
            m_queueGlasses.erase(it);
            return true;
        }
        return false;
    }
    bool CMaster::glassFromInPorcessToComplete(CGlass* pGlass)
    {
        auto it = std::find(m_inProcesGlasses.begin(), m_inProcesGlasses.end(), pGlass);
        if (it != m_inProcesGlasses.end()) {
            m_completeGlasses.push_back(*it);
            m_inProcesGlasses.erase(it);
            return true;
        }
        return false;
    }
}
SourceCode/Bond/Servo/CMaster.h
@@ -39,6 +39,7 @@
        STARTING,
        RUNNING,
        RUNNING_CONTINUOUS_TRANSFER,
        RUNNING_BATCH,
        STOPPING,
        MSERROR
    };
@@ -79,6 +80,7 @@
        int term();
        int start();
        int startContinuousTransfer();
        int startBatch();
        int stop();
        void clearError();
        ULONGLONG getRunTime();
@@ -98,6 +100,7 @@
        void setPortCassetteType(unsigned int index, SERVO::CassetteType type);
        void setPortEnable(unsigned int index, BOOL bEnable);
        void setCompareMapsBeforeProceeding(BOOL bCompare);
        void setJobMode(BOOL bJobMode);
        void datetimeSync(SYSTEMTIME& time);
        void enableEventReport(bool bEnable);
        void enableAlarmReport(bool bEnable);
@@ -137,7 +140,7 @@
        void setState(MASTERSTATE state);
        CRobotTask* createTransferTask(CEquipment* pSrcEq, CEquipment* pTarEq,
            MaterialsType primaryType = MaterialsType::G1, MaterialsType secondaryType = MaterialsType::G2,
            int armNo = 1);
            int armNo = 1, BOOL bJobMode = FALSE);
        CRobotTask* createTransferTask_bonder_to_bakecooling(CEquipment* pSrcEq, CEquipment* pTarEq);
        CRobotTask* createTransferTask_bake_to_cooling(CEquipment* pSrcEq);
        CRobotTask* createTransferTask_bakecooling_to_measurement(CEquipment* pSrcEq, CEquipment* pTarEq);
@@ -153,6 +156,15 @@
        bool slotUsable(const std::string& carrierId, uint16_t slot) const override;
        bool ceidDefined(uint32_t ceid) const override;
    public:
        // 新增函数
        CProcessJob* acquireNextProcessJob();
        CGlass* acquireNextGlass();
        int acquireGlassToQueue();
        bool addGlassToQueue(CGlass* pGlass);
        bool glassFromQueueToInPorcess(CGlass* pGlass);
        bool glassFromInPorcessToComplete(CGlass* pGlass);
    private:
        CRITICAL_SECTION m_criticalSection;
        MasterListener m_listener;
@@ -161,6 +173,7 @@
        std::string m_strFilepath;
        BOOL m_bDataModify;
        bool m_bContinuousTransfer;
        bool m_bBatch;
    private:
        /* 监控比特位的线程*/
@@ -189,11 +202,19 @@
        // 在开始工艺前是否先需要先比较map
        BOOL m_isCompareMapsBeforeProceeding;
        BOOL m_bJobMode;
        // 千传圈数计数
        int m_nContinuousTransferCount;
        int m_nContinuousTransferStep;
        // 新增已经开始处理的ProcessJob列表
        std::vector<CProcessJob*> m_inProcesJobs;
        std::vector<CGlass*> m_queueGlasses;
        std::vector<CGlass*> m_inProcesGlasses;
        std::vector<CGlass*> m_completeGlasses;
    private:
        bool m_bEnableEventReport;
        bool m_bEnableAlarmReport;
SourceCode/Bond/Servo/Configuration.cpp
@@ -160,6 +160,11 @@
    return GetPrivateProfileInt(_T("Master"), _T("CompareMapsBeforeProceeding"), 0, m_strFilepath);
}
BOOL CConfiguration::isJobMode()
{
    return GetPrivateProfileInt(_T("Master"), _T("JobMode"), 0, m_strFilepath);
}
void CConfiguration::setContinuousTransferCount(int round)
{
    WritePrivateProfileString(_T("Master"), _T("CTRound"),
SourceCode/Bond/Servo/Configuration.h
@@ -27,6 +27,7 @@
    BOOL setPortCassetteType(unsigned int index, int cassetteType);
    BOOL setPortEnable(unsigned int index, BOOL bEnable);
    BOOL isCompareMapsBeforeProceeding();
    BOOL isJobMode();
    void setContinuousTransferCount(int round);
    int getContinuousTransferCount();
SourceCode/Bond/Servo/Model.cpp
@@ -396,6 +396,7 @@
    strMasterDataFile.Format(_T("%s\\Master.dat"), (LPTSTR)(LPCTSTR)m_strWorkDir);
    m_master.setCacheFilepath((LPTSTR)(LPCTSTR)strMasterDataFile);
    m_master.setCompareMapsBeforeProceeding(m_configuration.isCompareMapsBeforeProceeding());
    m_master.setJobMode(m_configuration.isJobMode());
    // 加截Job
    strMasterDataFile.Format(_T("%s\\MasterState.dat"), (LPTSTR)(LPCTSTR)m_strWorkDir);
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/ServoDlg.cpp
@@ -192,6 +192,7 @@
                SERVO::MASTERSTATE state = theApp.m_model.getMaster().getState();
                if (state == SERVO::MASTERSTATE::READY) {
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_BATCH)->EnableWindow(TRUE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(TRUE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_NORMAL);
@@ -208,14 +209,17 @@
                }
                else if (state == SERVO::MASTERSTATE::MSERROR) {
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_BATCH)->EnableWindow(TRUE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(TRUE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_ALARM);
                    m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
                    m_pMyStatusbar->setRunTimeText("启动失败.");
                }
                else if (state == SERVO::MASTERSTATE::RUNNING || state == SERVO::MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
                else if (state == SERVO::MASTERSTATE::RUNNING || state == SERVO::MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER
                    || state == SERVO::MASTERSTATE::RUNNING_BATCH) {
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_BATCH)->EnableWindow(FALSE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(FALSE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(TRUE);
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_RUNNING);
@@ -959,6 +963,19 @@
        else {
            if (theApp.m_model.getMaster().start() == 0) {
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_BATCH)->EnableWindow(FALSE);
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(FALSE);
            }
        }
    }
    else if (id == IDC_BUTTON_RUN_BATCH) {
        if (theApp.m_model.getMaster().getState() == SERVO::MASTERSTATE::MSERROR) {
            AfxMessageBox("当前有机台发生错误,不能启动,请确认解决问题后再尝试重新启动!");
        }
        else {
            if (theApp.m_model.getMaster().startBatch() == 0) {
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_BATCH)->EnableWindow(FALSE);
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(FALSE);
            }
        }
@@ -970,6 +987,7 @@
        else {
            if (theApp.m_model.getMaster().startContinuousTransfer() == 0) {
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_BATCH)->EnableWindow(FALSE);
                m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(FALSE);
            }
        }
@@ -1099,6 +1117,9 @@
    else if (state == SERVO::MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER) {
        strText.Format(_T("千传模式:%02d:%02d:%02d   %s"), h, m, s, pszSuffix);
    }
    else if (state == SERVO::MASTERSTATE::RUNNING_BATCH) {
        strText.Format(_T("JOB模式:%02d:%02d:%02d   %s"), h, m, s, pszSuffix);
    }
    else {
        strText.Format(_T("已运行:%02d:%02d:%02d   %s"), h, m, s, pszSuffix);
    }
SourceCode/Bond/Servo/TopToolbar.cpp
@@ -8,6 +8,9 @@
#include "Common.h"
#define SHOW_BATCH    1
#define SHOW_CT        1
// CTopToolbar 对话框
IMPLEMENT_DYNAMIC(CTopToolbar, CDialogEx)
@@ -27,6 +30,7 @@
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_BUTTON_RUN, m_btnRun);
    DDX_Control(pDX, IDC_BUTTON_RUN_BATCH, m_btnRunBatch);
    DDX_Control(pDX, IDC_BUTTON_RUN_CT, m_btnRunCt);
    DDX_Control(pDX, IDC_BUTTON_STOP, m_btnStop);
    DDX_Control(pDX, IDC_BUTTON_JOBS, m_btnCJobs);
@@ -54,6 +58,7 @@
    CDialogEx::OnInitDialog();
    InitBtn(m_btnRun, "Run_High_32.ico", "Run_Gray_32.ico");
    InitBtn(m_btnRunBatch, "Run_High_32.ico", "Run_Gray_32.ico");
    InitBtn(m_btnRunCt, "RunCt_High_32.ico", "RunCt_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");
@@ -120,10 +125,19 @@
    x += BTN_WIDTH;
    x += 2;
#ifdef SHOW_BATCH
    pItem = GetDlgItem(IDC_BUTTON_RUN_BATCH);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
#endif
#ifdef SHOW_CT
    pItem = GetDlgItem(IDC_BUTTON_RUN_CT);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
#endif
    pItem = GetDlgItem(IDC_BUTTON_STOP);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
@@ -204,6 +218,7 @@
{
    switch (LOWORD(wParam)) {
    case IDC_BUTTON_RUN:
    case IDC_BUTTON_RUN_BATCH:
    case IDC_BUTTON_RUN_CT:
    case IDC_BUTTON_STOP:
    case IDC_BUTTON_JOBS:
SourceCode/Bond/Servo/TopToolbar.h
@@ -31,6 +31,7 @@
private:
    CBlButton m_btnRun;
    CBlButton m_btnRunBatch;
    CBlButton m_btnRunCt;
    CBlButton m_btnStop;
    CBlButton m_btnCJobs;
SourceCode/Bond/Servo/resource.h
Binary files differ