LAPTOP-SNT8I5JK\Boounion
2025-06-09 3404823d074a08b8c0824b505db16168f7e66201
Merge branch 'clh'
已修改17个文件
256 ■■■■ 文件已修改
SourceCode/Bond/Servo/CBakeCooling.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.cpp 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipment.h 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipmentPage2.cpp 64 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipmentPage2.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CLoadPort.cpp 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageGraph2.cpp 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotTask.cpp 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotTask.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotTaskDlg.cpp 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CSlot.cpp 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CSlot.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Context.cpp 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.cpp 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CBakeCooling.cpp
@@ -45,18 +45,22 @@
        m_slot[0].setPosition(m_nID);
        m_slot[0].setNo(1);
        m_slot[0].setName("Bake 1");
        m_slot[0].setLinkSignalPath(0);
        m_slot[1].enable();
        m_slot[1].setPosition(m_nID);
        m_slot[1].setNo(2);
        m_slot[1].setName("Bake 2");
        m_slot[1].setLinkSignalPath(0);
        m_slot[2].enable();
        m_slot[2].setPosition(m_nID);
        m_slot[2].setNo(3);
        m_slot[2].setName("Cooling 1");
        m_slot[2].setLinkSignalPath(1);
        m_slot[3].enable();
        m_slot[3].setPosition(m_nID);
        m_slot[3].setNo(4);
        m_slot[3].setName("Cooling 2");
        m_slot[3].setLinkSignalPath(1);
    }
    void CBakeCooling::onTimer(UINT nTimerid)
SourceCode/Bond/Servo/CEquipment.cpp
@@ -47,7 +47,6 @@
        for (int i = 0; i < SLOT_MAX; i++) {
            CContext* pContext = m_slot[i].getContext();
            if (pContext != nullptr) {
                pContext->release();
                m_slot[i].setContext(nullptr);
            }
        }
@@ -1149,10 +1148,11 @@
            if (m_slot[i].isLock()) continue;
            CGlass* pGlass = (CGlass*)m_slot[i].getContext();
            if (pGlass == nullptr) continue;
            if(!m_bLinkSignal[0][SIGNAL_UPSTREAM_INLINE]
                || m_bLinkSignal[0][SIGNAL_UPSTREAM_TROUBLE]
                || !m_bLinkSignal[0][SIGNAL_INTERLOCK]
                || !m_bLinkSignal[0][SIGNAL_SEND_ABLE] ) continue;
            int lsPath = m_slot[i].getLinkSignalPath();
            if(!m_bLinkSignal[lsPath][SIGNAL_UPSTREAM_INLINE]
                || m_bLinkSignal[lsPath][SIGNAL_UPSTREAM_TROUBLE]
                || !m_bLinkSignal[lsPath][SIGNAL_INTERLOCK]
                || !m_bLinkSignal[lsPath][SIGNAL_SEND_ABLE] ) continue;
            MaterialsType glassType = pGlass->getType();
            if (glassType == MaterialsType::G1 && putSlotType == MaterialsType::G2) continue;
@@ -1173,10 +1173,11 @@
                    if (m_slot[i].isLock()) continue;
                    CGlass* pGlass = (CGlass*)m_slot[i].getContext();
                    if (pGlass == nullptr) continue;
                    if (!m_bLinkSignal[0][SIGNAL_UPSTREAM_INLINE]
                        || m_bLinkSignal[0][SIGNAL_UPSTREAM_TROUBLE]
                        || !m_bLinkSignal[0][SIGNAL_INTERLOCK]
                        || !m_bLinkSignal[0][SIGNAL_SEND_ABLE]) continue;
                    int lsPath = m_slot[i].getLinkSignalPath();
                    if (!m_bLinkSignal[lsPath][SIGNAL_UPSTREAM_INLINE]
                        || m_bLinkSignal[lsPath][SIGNAL_UPSTREAM_TROUBLE]
                        || !m_bLinkSignal[lsPath][SIGNAL_INTERLOCK]
                        || !m_bLinkSignal[lsPath][SIGNAL_SEND_ABLE]) continue;
                    MaterialsType glassType = pGlass->getType();
                    if (glassType == MaterialsType::G1 && putSlotType == MaterialsType::G2) continue;
@@ -1188,6 +1189,12 @@
        }
        return nullptr;
    }
    CSlot* CEquipment::getSlot(int index)
    {
        if (index >= SLOT_MAX) return nullptr;
        return &m_slot[index];
    }
    CGlass* CEquipment::getGlassFromSlot(int slotNo)
@@ -1229,6 +1236,21 @@
        return TRUE;
    }
    int CEquipment::removeGlass(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 -1;
        pSlot->setContext(nullptr);
        return 0;
    }
    short CEquipment::decodeRecipeListReport(const char* pszData, size_t size)
    {
        return m_recipesManager.decodeRecipeListReport(pszData, size);
SourceCode/Bond/Servo/CEquipment.h
@@ -150,6 +150,9 @@
        // unitNo: 0:local; Others:unit No
        int recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo);
        // 获取指定的Slot
        CSlot* getSlot(int index);
        // 获取一个可用的槽位
        CSlot* getAvailableSlot();
@@ -182,6 +185,8 @@
        // 指定槽位是否可以放置玻璃
        BOOL canPlaceGlassInSlot(const short slotIndex);
        // 手动移除物料
        int removeGlass(int slotNo);
    // 以下为从CC-Link读取到的Bit标志位检测函数
    public:
SourceCode/Bond/Servo/CEquipmentPage2.cpp
@@ -74,25 +74,15 @@
    ListView_SetImageList(m_listCtrl.GetSafeHwnd(), imageList, LVSIL_SMALL);
    m_listCtrl.InsertColumn(0, _T(""), LVCFMT_RIGHT, width[0]);
    m_listCtrl.InsertColumn(1, _T("ID"), LVCFMT_LEFT, width[1]);
    m_listCtrl.InsertColumn(2, _T("贴合"), LVCFMT_LEFT, width[2]);
    m_listCtrl.InsertColumn(3, _T("时间"), LVCFMT_LEFT, width[3]);
    m_listCtrl.SetColumnWidth(3, LVSCW_AUTOSIZE_USEHEADER);
    m_listCtrl.InsertColumn(2, _T("名称"), LVCFMT_LEFT, width[2]);
    m_listCtrl.InsertColumn(3, _T("Glass ID"), LVCFMT_LEFT, width[3]);
    m_listCtrl.InsertColumn(4, _T("贴合Glass ID"), LVCFMT_LEFT, width[4]);
    m_listCtrl.InsertColumn(5, _T("时间"), LVCFMT_LEFT, width[5]);
    m_listCtrl.SetColumnWidth(5, LVSCW_AUTOSIZE_USEHEADER);
    ASSERT(m_pEquipment);
    for (int i = 0; i < SLOT_MAX; i++) {
        SERVO::CGlass* pGlass = m_pEquipment->getGlassFromSlot(i+1);
        if (pGlass != nullptr) {
            pGlass->addRef();
            SERVO::CGlass* pBuddy = pGlass->getBuddy();
            int index = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), _T(""));
            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());
            }
        }
    }
    UpdateSlots();
    return TRUE;  // return TRUE unless you set the focus to a control
                  // 异常: OCX 属性页应返回 FALSE
@@ -122,11 +112,6 @@
        strItem.Format(_T("Col_%d_Width"), i);
        strTemp.Format(_T("%d"), rect.right - rect.left);
        WritePrivateProfileString("EquipmentPage2ListCtrl", strItem, strTemp, strIniFile);
    }
    for (int i = 0; i < m_listCtrl.GetItemCount(); i++) {
        SERVO::CGlass* pGlass = (SERVO::CGlass*)m_listCtrl.GetItemData(i);
        pGlass->release();
    }
}
@@ -171,16 +156,37 @@
void CEquipmentPage2::OnBnClickedButtonRemove()
{
    /*
    int index = GetSelectedItemIndex();
    if (index >= 0) {
        SERVO::CGlass* pGlass = (SERVO::CGlass*)m_listCtrl.GetItemData(index);
        ASSERT(m_pEquipment);
        BOOL bRet = m_pEquipment->removeClass(pGlass);
        if (bRet) {
            pGlass->release();
            m_listCtrl.DeleteItem(index);
        SERVO::CSlot* pSlot = (SERVO::CSlot*)m_listCtrl.GetItemData(index);
        ASSERT(pSlot);
        int bRet = m_pEquipment->removeGlass(pSlot->getNo());
        if (bRet == 0) {
            UpdateSlots();
        }
    }
    */
}
void CEquipmentPage2::UpdateSlots()
{
    m_listCtrl.DeleteAllItems();
    for (int i = 0; i < SLOT_MAX; i++) {
        SERVO::CSlot* pSlot = m_pEquipment->getSlot(i);
        if (pSlot != nullptr && pSlot->isEnable()) {
            int index = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), _T(""));
            m_listCtrl.SetItemData(index, (DWORD_PTR)pSlot);
            m_listCtrl.SetItemText(index, 1, std::to_string(pSlot->getNo()).c_str());
            m_listCtrl.SetItemText(index, 2, pSlot->getName().c_str());
            SERVO::CGlass* pGlass = (SERVO::CGlass*)pSlot->getContext();
            if (pGlass != nullptr) {
                m_listCtrl.SetItemText(index, 3, pGlass->getID().c_str());
                SERVO::CGlass* pBuddy = pGlass->getBuddy();
                if (pBuddy != nullptr) {
                    m_listCtrl.SetItemText(index, 4, pBuddy->getID().c_str());
                }
            }
        }
    }
}
SourceCode/Bond/Servo/CEquipmentPage2.h
@@ -18,6 +18,7 @@
private:
    int GetSelectedItemIndex();
    void UpdateSlots();
private:
    SERVO::CEquipment* m_pEquipment;
SourceCode/Bond/Servo/CLoadPort.cpp
@@ -1103,7 +1103,6 @@
            pGlass->setJobDataB(&jb);
            pGlass->setType(type);
            pGlass->setJobDataS(&js);
            pGlass->addRef();
            m_slot[i].setContext(pGlass);
        }
SourceCode/Bond/Servo/CMaster.cpp
@@ -287,6 +287,7 @@
        // 各种机器
        CEFEM* pEFEM = (CEFEM*)getEquipment(EQ_ID_EFEM);
        CLoadPort* pLoadPort1 = (CLoadPort*)getEquipment(EQ_ID_LOADPORT1);
        CLoadPort* pLoadPort2 = (CLoadPort*)getEquipment(EQ_ID_LOADPORT2);
        CFliper* pFliper = (CFliper*)getEquipment(EQ_ID_FLIPER);
@@ -297,6 +298,7 @@
        CBakeCooling* pBakeCooling = (CBakeCooling*)getEquipment(EQ_ID_BAKE_COOLING);
        CMeasurement* pMeasurement = (CMeasurement*)getEquipment(EQ_ID_MEASUREMENT);
        ASSERT(pEFEM);
        ASSERT(pLoadPort1);
        ASSERT(pLoadPort2);
        ASSERT(pFliper);
@@ -372,6 +374,7 @@
                // BakeCooling ->Measurement
                m_pActiveRobotTask = createTransferTask_bakecooling_to_measurement(pBakeCooling, pMeasurement);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -386,6 +389,7 @@
                // Bake -> Cooling
                m_pActiveRobotTask = createTransferTask_bake_to_cooling(pBakeCooling);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -399,6 +403,7 @@
                // Bonder -> BakeCooling
                m_pActiveRobotTask = createTransferTask_bonder_to_bakecooling(pBonder1, pBakeCooling);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -410,6 +415,7 @@
                m_pActiveRobotTask = createTransferTask_bonder_to_bakecooling(pBonder2, pBakeCooling);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -422,6 +428,7 @@
                // Aligner -> Bonder
                m_pActiveRobotTask = createTransferTask(pAligner, pBonder1, primaryType, secondaryType);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -433,6 +440,7 @@
                m_pActiveRobotTask = createTransferTask(pAligner, pBonder2, primaryType, secondaryType);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -447,6 +455,7 @@
                // VacuumBake(G1) -> Aligner
                m_pActiveRobotTask = createTransferTask(pFliper, pAligner, primaryType, secondaryType);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -458,6 +467,7 @@
                m_pActiveRobotTask = createTransferTask(pVacuumBack, pAligner, primaryType, secondaryType);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -478,6 +488,7 @@
                }
                m_pActiveRobotTask = createTransferTask(pLoadPort1, pEqTar1, primaryType, secondaryType);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -489,6 +500,7 @@
                m_pActiveRobotTask = createTransferTask(pLoadPort2, pEqTar1, primaryType, secondaryType);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -503,6 +515,7 @@
                // LoadPort -> VacuumBake(G1)
                m_pActiveRobotTask = createTransferTask(pLoadPort1, pEqTar2, primaryType, secondaryType);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -514,6 +527,7 @@
                m_pActiveRobotTask = createTransferTask(pLoadPort2, pEqTar2, primaryType, secondaryType);
                if (m_pActiveRobotTask != nullptr) {
                    m_pActiveRobotTask->run();
                    std::string strDescription = m_pActiveRobotTask->getDescription();
                    unlock();
                    if (m_listener.onRobotTaskEvent != nullptr) {
@@ -1131,6 +1145,7 @@
        if (pSrcSlot != nullptr && nullptr != pTarSlot) {
            pTask = new CRobotTask();
            pTask->setContext(pSrcSlot->getContext());
            pTask->setEFEM((CEFEM*)getEquipment(EQ_ID_EFEM));
            pTask->setRobotTransferParam(++taskSeqNo, 1, pSrcSlot->getPosition(),
                pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo());
        }
@@ -1151,6 +1166,7 @@
        if (pSrcSlot != nullptr && nullptr != pTarSlot) {
            pTask = new CRobotTask();
            pTask->setContext(pSrcSlot->getContext());
            pTask->setEFEM((CEFEM*)getEquipment(EQ_ID_EFEM));
            pTask->setRobotTransferParam(++taskSeqNo, 1, pSrcSlot->getPosition(),
                pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo());
        }
@@ -1172,6 +1188,7 @@
        if (pSrcSlot != nullptr && nullptr != pTarSlot) {
            pTask = new CRobotTask();
            pTask->setContext(pSrcSlot->getContext());
            pTask->setEFEM((CEFEM*)getEquipment(EQ_ID_EFEM));
            pTask->setRobotTransferParam(++taskSeqNo, 1, pSrcSlot->getPosition(),
                pTarSlot->getPosition(), pSrcSlot->getNo(), pTarSlot->getNo());
        }
@@ -1200,4 +1217,28 @@
        return pTask;
    }
    int CMaster::abortCurrentTask()
    {
        lock();
        if (m_pActiveRobotTask != nullptr) {
            m_pActiveRobotTask->abort();
        }
        unlock();
        if (m_listener.onRobotTaskEvent != nullptr) {
            m_listener.onRobotTaskEvent(this, m_pActiveRobotTask, ROBOT_EVENT_ABORT);
        }
        lock();
        if (m_pActiveRobotTask != nullptr) {
            delete m_pActiveRobotTask;
            m_pActiveRobotTask = nullptr;
        }
        unlock();
        // 当前任务手动中止后,停止调度,需要操作员在解决问题后,重新启动
        stop();
        return 0;
    }
}
SourceCode/Bond/Servo/CMaster.h
@@ -63,6 +63,7 @@
        std::list<CEquipment*>& getEquipmentList();
        CEquipment* getEquipment(int id);
        void setCacheFilepath(const char* pszFilepath);
        int abortCurrentTask();
    private:
        inline void lock() { EnterCriticalSection(&m_criticalSection); }
SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -148,7 +148,7 @@
        CEquipmentPage2* pPage2 = new CEquipmentPage2();
        pPage2->setEquipment(pEquipment);
        pPage2->Create(IDD_PAGE_EQUIPMENT2);
        dlg.addPage(pPage2, "Glass");
        dlg.addPage(pPage2, "Slots");
        if (pEquipment->getID() == EQ_ID_EFEM) {
            CEquipmentPage3* pPage3 = new CEquipmentPage3();
@@ -269,6 +269,10 @@
                pEquipment->setLinkSignal(0, SIGNAL_UPSTREAM_TROUBLE, FALSE);
                pEquipment->setLinkSignal(0, SIGNAL_INTERLOCK, TRUE);
                pEquipment->setLinkSignal(0, SIGNAL_SEND_ABLE, TRUE);
                pEquipment->setLinkSignal(1, SIGNAL_UPSTREAM_INLINE, TRUE);
                pEquipment->setLinkSignal(1, SIGNAL_UPSTREAM_TROUBLE, FALSE);
                pEquipment->setLinkSignal(1, SIGNAL_INTERLOCK, TRUE);
                pEquipment->setLinkSignal(1, SIGNAL_SEND_ABLE, TRUE);
            }
            if (pEquipment != nullptr && (pEquipment->getID() == EQ_ID_Bonder1
SourceCode/Bond/Servo/CRobotTask.cpp
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "CRobotTask.h"
#include "ToolUnits.h"
#include "Log.h"
namespace SERVO {
@@ -13,6 +14,7 @@
        m_timeStored = 0;
        m_timeFinish = 0;
        m_pContext = nullptr;
        m_pEFEM = nullptr;
    }
    CRobotTask::~CRobotTask()
@@ -78,6 +80,11 @@
        return m_pContext;
    }
    void CRobotTask::setEFEM(CEFEM* pEFEM)
    {
        m_pEFEM = pEFEM;
    }
    std::string& CRobotTask::generateId(std::string& out)
    {
        char szBuffer[256];
@@ -139,6 +146,30 @@
        return m_state;
    }
    void CRobotTask::run()
    {
        ASSERT(m_pEFEM);
        m_state = ROBOT_TASK_STATE::Running;
        static int seq = 0;
        m_pEFEM->robotSendTransfer(++seq,
            m_robotCmdParam.armNo,
            m_robotCmdParam.getPosition,
            m_robotCmdParam.putPosition,
            m_robotCmdParam.getSlotNo,
            m_robotCmdParam.putSlotNo,
            [&](int code) -> int {
                if (code == WOK) {
                    LOGI(_T("RobotTask已下发到EFEM"));
                }
                else {
                    LOGI(_T("RobotTask已下发失败"));
                }
                return 0;
            });
    }
    void CRobotTask::completed()
    {
        m_state = ROBOT_TASK_STATE::Completed;
SourceCode/Bond/Servo/CRobotTask.h
@@ -1,6 +1,7 @@
#pragma once
#include "ServoCommo.h"
#include "Context.h"
#include "CEFEM.h"
namespace SERVO {
@@ -16,6 +17,7 @@
        std::string getSimpleDescription() const;
        void setContext(CContext* pContext);
        CContext* getContext();
        void setEFEM(CEFEM* pEFEM);
        void setRobotTransferParam(int seq, int armNo, int fromPos, int toPos, int fromSlot, int toSlot);
        ROBOT_CMD_PARAM& getRobotCmdParam();
        time_t getCreateTime();
@@ -23,6 +25,7 @@
        time_t getStoredTime();
        time_t getFinishTime();
        ROBOT_TASK_STATE getState();
        void run();
        void completed();
        void error();
        void abort();
@@ -50,5 +53,6 @@
        time_t m_timeFinish;                        /* 结束时间 */
        ROBOT_CMD_PARAM m_robotCmdParam;            /* 参数 */
        CContext* m_pContext;
        CEFEM* m_pEFEM;
    };
}
SourceCode/Bond/Servo/CRobotTaskDlg.cpp
@@ -194,8 +194,10 @@
void CRobotTaskDlg::OnBnClickedAbortTask()
{
    if (m_pRobotTask) {
        m_pRobotTask->abort();
        AfxMessageBox(_T("任务已停止。"));
    int ret = AfxMessageBox(_T("确认要终止当前搬送任务吗?除非发生了异常,否则请不要手动终止任务!"), MB_OKCANCEL | MB_ICONEXCLAMATION);
    if (ret != IDOK) {
        return;
    }
    theApp.m_model.getMaster().abortCurrentTask();
}
SourceCode/Bond/Servo/CSlot.cpp
@@ -12,6 +12,7 @@
        m_bLock = FALSE;
        m_pContext = nullptr;
        m_pTempContext = nullptr;
        m_nLinkSignalPath = 0;
    }
    CSlot::~CSlot()
@@ -119,6 +120,16 @@
        return m_pTempContext;
    }
    void CSlot::setLinkSignalPath(int path)
    {
        m_nLinkSignalPath = path;
    }
    int CSlot::getLinkSignalPath()
    {
        return m_nLinkSignalPath;
    }
    void CSlot::serialize(CArchive& ar)
    {
        if (ar.IsStoring()) {
SourceCode/Bond/Servo/CSlot.h
@@ -29,6 +29,8 @@
        CContext* getContext();
        CContext* getTempContext();
        void setContext(CContext* pContext);
        void setLinkSignalPath(int path);
        int getLinkSignalPath();
        void serialize(CArchive& ar);
    private:
@@ -44,6 +46,7 @@
        CContext* m_pTempContext;
        BOOL m_bEnable;
        BOOL m_bLock;
        int m_nLinkSignalPath;
    };
}
SourceCode/Bond/Servo/Context.cpp
@@ -1,7 +1,34 @@
#include "stdafx.h"
#include "Context.h"
#include <dbghelp.h>
#pragma comment(lib, "dbghelp.lib")
void PrintStackTrace()
{
    void* stack[62]; // 最多抓62层
    USHORT frames = CaptureStackBackTrace(0, 62, stack, NULL);
    HANDLE process = GetCurrentProcess();
    SymInitialize(process, NULL, TRUE);
    for (USHORT i = 0; i < frames; ++i) {
        DWORD64 address = (DWORD64)(stack[i]);
        char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
        PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
        symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
        symbol->MaxNameLen = MAX_SYM_NAME;
        if (SymFromAddr(process, address, 0, symbol)) {
            TRACE(">>>> name:%s\n", symbol->Name);
        }
        else {
            TRACE(">>>> name:%s\n", "SymFromAddr failed");
        }
    }
    SymCleanup(process);
}
CContext::CContext()
{
    m_onReleaseCallback = nullptr;
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/ServoDlg.cpp
@@ -174,6 +174,8 @@
            else if (RX_CODE_MASTER_STATE_CHANGED == code) {
                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_STOP)->EnableWindow(FALSE);
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_NORMAL);
                    m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
                    KillTimer(TIMER_ID_UPDATE_RUMTIME);
@@ -182,6 +184,8 @@
                    m_pMyStatusbar->setRunTimeText((LPTSTR)(LPCTSTR)strText);
                }
                else if (state == SERVO::MASTERSTATE::RUNNING) {
                    m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(TRUE);
                    m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_RUNNING);
                    m_pMyStatusbar->setForegroundColor(RGB(255, 255, 255));
                    SetTimer(TIMER_ID_UPDATE_RUMTIME, 500, nullptr);
@@ -207,6 +211,9 @@
                        }
                    }
                    else if (exCode == ROBOT_EVENT_FINISH) {
                        m_pMyStatusbar->setCurTaskBtnText("无");
                    }
                    else if (exCode == ROBOT_EVENT_ABORT) {
                        m_pMyStatusbar->setCurTaskBtnText("无");
                    }
                }
@@ -793,11 +800,9 @@
    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) {