chenluhua1980
6 天以前 d400f022161ff47f02cd0ea95a5076d0187ecd4d
SourceCode/Bond/Servo/PortConfigurationDlg.cpp
@@ -11,8 +11,6 @@
#include "RecipeManager.h"
#include "ServoCommo.h"
#define CHECKBOX_ALL_ID        0x1234
// CPortConfigurationDlg 对话框
@@ -56,6 +54,10 @@
        return;
    }
    CStringArray permissions;
    permissions.Add(_T("G1"));
    permissions.Add(_T("G2"));
    SetDlgItemText(IDC_EDIT_LOTID, "");
    SetDlgItemText(IDC_EDIT_PRODUCTID, "");
    SetDlgItemText(IDC_EDIT_OPERATIONID, "");
@@ -68,11 +70,11 @@
            continue;
        }
        // 设置 Panel ID 和勾选框
        SERVO::CGlass* pGlass = dynamic_cast<SERVO::CGlass*>(pSlot->getContext());
        SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS();
        int nRow = i + 1;
        if (pGlass != nullptr) {
        if (pGlass != nullptr && pJobDataS != nullptr) {
            m_wndGrid.SetItemState(nRow, 0, GVIS_READONLY);
            m_wndGrid.SetItemText(nRow, 0, pSlot->getName().c_str());
            m_wndGrid.SetCellType(nRow, 1, RUNTIME_CLASS(CGridCellCheck));
@@ -80,18 +82,44 @@
            ASSERT(pCheck);
            pCheck->SetCheck(pGlass->isScheduledForProcessing());
            pCheck->SetText(pGlass->getID().c_str());
            if (m_wndGrid.SetCellType(nRow, 2, RUNTIME_CLASS(CGridCellCombo))) {
                CGridCellCombo* pCell = static_cast<CGridCellCombo*>(m_wndGrid.GetCell(nRow, 2));
                pCell->SetOptions(permissions);
                pCell->SetStyle(CBS_DROPDOWNLIST);
                int nMaterialsType = pJobDataS->getMaterialsType() - 1;
                if (nMaterialsType < 0 || nMaterialsType > 2) {
                    nMaterialsType = 0;
                }
                m_wndGrid.SetItemText(nRow, 2, permissions.GetAt(nMaterialsType));
            }
        }
        m_wndGrid.SetItemData(nRow, 0, (LPARAM)pGlass);
        // 回填 Job 信息(只取第一个有效 Glass)
        if (!bJobInfoSet && pGlass) {
            SERVO::CJobDataS* pJS = pGlass->getJobDataS();
            if (pJS) {
            if (pJS) {
                int nRecipeID = pJobDataS->getMasterRecipe();
                std::string strRecipeName = RecipeManager::getInstance().getPPIDById(nRecipeID);
                SetDlgItemText(IDC_EDIT_LOTID, CString(pJS->getLotId().c_str()));
                SetDlgItemText(IDC_EDIT_PRODUCTID, CString(pJS->getProductId().c_str()));
                SetDlgItemText(IDC_EDIT_OPERATIONID, CString(pJS->getOperationId().c_str()));
                m_comboMaterialsType.SetCurSel(pJS->getMaterialsType() - 1);
                if (!strRecipeName.empty()) {
                    CString csRecipeName(strRecipeName.c_str());
                    int nIndex = m_comboRecipe.FindStringExact(-1, csRecipeName);
                    if (nIndex != CB_ERR) {
                        m_comboRecipe.SetCurSel(nIndex);
                    }
                    else {
                  AfxMessageBox(_T("当前配方在系统中不存在,请重新选择!"), MB_ICONWARNING);
                        m_comboRecipe.SetCurSel(0);
                    }
            }
                bJobInfoSet = true;
            }
        }
@@ -105,7 +133,7 @@
        return;
    }
    const int nCols = 2;
    const int nCols = 3;
    const int nFixRows = 1;
   const int nRows = SLOT_MAX + 1; // 存在表头,所以 +1
@@ -130,6 +158,8 @@
    m_wndGrid.SetItemText(0, nColIdx++, _T("Slot ID"));
    m_wndGrid.SetColumnWidth(nColIdx, 60);
    m_wndGrid.SetItemText(0, nColIdx++, _T("Glass ID"));
    m_wndGrid.SetColumnWidth(nColIdx, 60);
    m_wndGrid.SetItemText(0, nColIdx++, _T("物料类型"));
    // 设置行为样式
@@ -137,7 +167,7 @@
    m_wndGrid.SetFixedColumnSelection(FALSE);
    m_wndGrid.SetEditable(TRUE);
    m_wndGrid.SetRowResize(FALSE);
    m_wndGrid.SetColumnResize(TRUE);
    m_wndGrid.SetColumnResize(FALSE);
    m_wndGrid.SetListMode(TRUE);
    m_wndGrid.EnableSelection(TRUE);
    m_wndGrid.SetSingleRowSelection(TRUE);
@@ -219,7 +249,7 @@
        m_comboMaterialsType.AddString(item);
    }
    m_comboMaterialsType.SetCurSel(0);  // 默认选择第一个物料类型
    m_comboMaterialsType.EnableWindow(FALSE);
    InitGrid();
   LoadPortConfigToUI(m_pPort[0]);     // 默认加载第一个端口的配置
@@ -234,7 +264,6 @@
    else {
        SetWindowText(_T("Port Configuration"));
    }
    // Porcess Start / Process Cancel 按钮状态
    GetDlgItem(IDC_BUTTON_PROCESS_START)->EnableWindow(FALSE);
@@ -282,16 +311,19 @@
        m_comboRecipe.GetLBText(selRecipe, str);
        config.strRecipe = CT2A(str.GetString());
    }
    int nRecipeID = RecipeManager::getInstance().getIdByPPID(config.strRecipe);
    RecipeInfo stRecipeInfo = RecipeManager::getInstance().getRecipeByPPID(config.strRecipe);
    std::vector<DeviceRecipe> vecRecipeInfo = stRecipeInfo.vecDeviceList;
    // 获取 Material Type 索引(索引从 0 开始,对应枚举从 1 开始)
    int selMaterial = m_comboMaterialsType.GetCurSel();
    if (selMaterial != CB_ERR) {
        config.nMaterialType = selMaterial + 1;
    }
   else {
      AfxMessageBox(_T("Please select a material type!"));
      return;
   }
    //int selMaterial = m_comboMaterialsType.GetCurSel();
    //if (selMaterial != CB_ERR) {
    //    config.nMaterialType = selMaterial + 1;
    //}
   //else {
   //   AfxMessageBox(_T("Please select a material type!"));
   //   return;
   //}
    // 获取 Lot ID / Product ID / Operation ID
    CString strText;
@@ -319,20 +351,20 @@
    // 获取 Grid 表格中 Slot 状态(第1~8行)
    for (int i = 1; i <= SLOT_MAX; ++i) {
        SERVO::CGlass* pGlass = (SERVO::CGlass*)m_wndGrid.GetItemData(i, 0);
        int nMaterialType = m_wndGrid.GetItemText(i, 2).CompareNoCase("G1") == 0 ? 1 : 2;
        if (pGlass != nullptr) {
            CGridCellCheck* pCheck = dynamic_cast<CGridCellCheck*>(m_wndGrid.GetCell(i, 1));
            ASSERT(pCheck);
            CGridCellCombo* pCombo = dynamic_cast<CGridCellCombo*>(m_wndGrid.GetCell(i, 2));
            ASSERT(pCheck && pCombo);
            pGlass->setScheduledForProcessing(pCheck->GetCheck());
            pGlass->setType(static_cast<SERVO::MaterialsType>(config.nMaterialType));
            pGlass->setType(static_cast<SERVO::MaterialsType>(nMaterialType));
            SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS();
            pJobDataS->setLotId(config.strLotID.c_str());
            pJobDataS->setProductId(config.strProductID.c_str());
            pJobDataS->setOperationId(config.strOperationID.c_str());
            pJobDataS->setMaterialsType(config.nMaterialType);
            RecipeInfo stRecipeInfo = RecipeManager::getInstance().getRecipeByPPID(config.strRecipe);
            std::vector<DeviceRecipe> vecRecipeInfo = stRecipeInfo.vecDeviceList;
            pJobDataS->setMaterialsType(nMaterialType);
            pJobDataS->setMasterRecipe(nRecipeID);
            for (const auto& info : vecRecipeInfo) {
                const std::string& name = info.strDeviceName;
@@ -406,14 +438,101 @@
{
    int selPort = (0 <= m_nCurSelPort && m_nCurSelPort <= 3) ? m_nCurSelPort
        : m_comboPort.GetCurSel();
    if (selPort < 0 || selPort >= 4) return;
    m_pPort[selPort]->sendCassetteCtrlCmd(CCC_PROCESS_START, nullptr, 0, 0, 0, nullptr, nullptr);
    if (selPort < 0 || selPort >= 4) {
        LOGE("ProcessStart invalid port index: %d", selPort);
        return;
    }
    SERVO::CLoadPort* pPort = m_pPort[selPort];
    if (pPort == nullptr) {
        LOGE("ProcessStart port pointer is null, index: %d", selPort);
        return;
    }
    constexpr short cmd = CCC_PROCESS_START;
    LOGI("ProcessStart request: port=%d, cmd=%d", selPort + 1, cmd);
    short jobExistence[12] = { 0 };
    short slotProcess = 0;
    short jobCount = 0; // 0 = Process All Glass (per spec)
    bool anyScheduled = false;
    // Prefer hardware scan map for job existence (first 16 slots).
    const short scanMap = pPort->getScanCassetteMap();
    if (scanMap != 0) {
        jobExistence[0] = scanMap;
    }
    // Build existence/selected maps from current glass list (up to 192 slots).
    const int maxSlots = 12 * 16;
    const int totalSlots = (SLOT_MAX < maxSlots) ? SLOT_MAX : maxSlots;
    for (int slot = 1; slot <= totalSlots; ++slot) {
        SERVO::CGlass* pGlass = pPort->getGlassFromSlot(slot);
        if (pGlass == nullptr) continue;
        const int wordIndex = (slot - 1) / 16;
        const int bitIndex = (slot - 1) % 16;
        jobExistence[wordIndex] = (short)(jobExistence[wordIndex] | (1 << bitIndex));
        if (slot <= 16 && pGlass->isScheduledForProcessing()) {
            slotProcess = (short)(slotProcess | (1 << bitIndex));
            anyScheduled = true;
        }
    }
    // If no slot explicitly selected, default to all existing in the first word.
    if (!anyScheduled) {
        slotProcess = jobExistence[0];
    }
    int ret = pPort->sendCassetteCtrlCmd(cmd, jobExistence, 12, slotProcess, jobCount, nullptr,
        [selPort](int code) -> int {
            if (code == WOK) {
                LOGI("ProcessStart write complete: port=%d, code=WOK", selPort + 1);
            }
            else {
                LOGE("ProcessStart write failed: port=%d, code=%d", selPort + 1, code);
            }
            return 0;
        });
    if (ret != 0) {
        LOGE("ProcessStart sendCassetteCtrlCmd immediate failure: port=%d, ret=%d", selPort + 1, ret);
    }
    else {
        LOGI("ProcessStart sendCassetteCtrlCmd dispatched: port=%d", selPort + 1);
    }
}
void CPortConfigurationDlg::OnBnClickedButtonProcessCancel()
{
    int selPort = (0 <= m_nCurSelPort && m_nCurSelPort <= 3) ? m_nCurSelPort
        : m_comboPort.GetCurSel();
    if (selPort < 0 || selPort >= 4) return;
    m_pPort[selPort]->sendCassetteCtrlCmd(CCC_PROCESS_CANCEL, nullptr, 0, 0, 0, nullptr, nullptr);
    if (selPort < 0 || selPort >= 4) {
        LOGE("ProcessCancel invalid port index: %d", selPort);
        return;
    }
    SERVO::CLoadPort* pPort = m_pPort[selPort];
    if (pPort == nullptr) {
        LOGE("ProcessCancel port pointer is null, index: %d", selPort);
        return;
    }
    constexpr short cmd = CCC_PROCESS_CANCEL;
    LOGI("ProcessCancel request: port=%d, cmd=%d", selPort + 1, cmd);
    int ret = pPort->sendCassetteCtrlCmd(cmd, nullptr, 0, 0, 0, nullptr,
        [selPort](int code) -> int {
            if (code == WOK) {
                LOGI("ProcessCancel write complete: port=%d, code=WOK", selPort + 1);
            }
            else {
                LOGE("ProcessCancel write failed: port=%d, code=%d", selPort + 1, code);
            }
            return 0;
        });
    if (ret != 0) {
        LOGE("ProcessCancel sendCassetteCtrlCmd immediate failure: port=%d, ret=%d", selPort + 1, ret);
    }
    else {
        LOGI("ProcessCancel sendCassetteCtrlCmd dispatched: port=%d", selPort + 1);
    }
}