LAPTOP-T815PCOQ\25526
2025-01-13 9ea5eea16629a2ab4473727e6b064f83f71aa46c
Merge branch 'clh' into liuyang

# Conflicts:
# SourceCode/Bond/BoounionPLC/BoounionPLC.rc
# SourceCode/Bond/BoounionPLC/Common.h
# SourceCode/Bond/BoounionPLC/Model.cpp
# SourceCode/Bond/BoounionPLC/Model.h
已添加23个文件
已修改13个文件
131704 ■■■■■ 文件已修改
Document/semi资料/semi璧勬枡/銆_銆戣澶囪嚜鍔ㄥ寲閫氫俊瑙勮寖聽Communication聽Specification聽for聽Equipment聽Automation-V3.pdf 补丁 | 查看 | 原始文档 | blame | 历史
Document/semi资料/semi资料/SEMI E05 - 0200.pdf 补丁 | 查看 | 原始文档 | blame | 历史
Document/semi资料/semi资料/SEMI E05 译文.docx 补丁 | 查看 | 原始文档 | blame | 历史
Document/semi资料/semi资料/SEMI E05 译文.pdf 127170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Document/semi资料/semi资料/SEMI E30 - 0200.pdf 补丁 | 查看 | 原始文档 | blame | 历史
Document/semi资料/semi资料/SEMI E37 - 0999_1_35_translate.pdf 补丁 | 查看 | 原始文档 | blame | 历史
Document/semi资料/semi资料/SEMI E84握手.pdf 补丁 | 查看 | 原始文档 | blame | 历史
Document/semi资料/semi资料/semi标准合集.pdf 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/AlarmMonitor.cpp 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/AxisDetailSettingsDlg.cpp 633 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/AxisDetailSettingsDlg.h 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/AxisSettingsDlg.cpp 1383 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/AxisSettingsDlg.h 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLC.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/CBaseDlg.cpp 348 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/CBaseDlg.h 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/CPageLogcat.cpp 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/CPageLogcat.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/Common.h 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/FileManager/AxisManager.cpp 297 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/FileManager/AxisManager.h 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/Model.cpp 138 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/Model.h 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/PLC.cpp 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/PLC.h 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/PlcView.cpp 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/PlcView.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/RegexEdit.cpp 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BoounionPLC/RegexEdit.h 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/SecsTestDlg.cpp 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/SecsTestDlg.h 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/BoounionPLC/Debug/PLCs/Bonder1/AlarmList.txt 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/BoounionPLC/Debug/PLCs/Bonder1/AxesConfiguration.xml 411 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/x64/BoounionPLC/Debug/PLCs/Bonder1/IOConfiguration.iom 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Document/semi×ÊÁÏ/semi资料/ã€_】设备自动化通信规范 Communication Specification for Equipment Automation-V3.pdf
Binary files differ
Document/semi×ÊÁÏ/semi×ÊÁÏ/SEMI E05 - 0200.pdf
Binary files differ
Document/semi×ÊÁÏ/semi×ÊÁÏ/SEMI E05 ÒëÎÄ.docx
Binary files differ
Document/semi×ÊÁÏ/semi×ÊÁÏ/SEMI E05 ÒëÎÄ.pdf
¶Ô±ÈÐÂÎļþ
ÎļþÌ«´ó
Document/semi×ÊÁÏ/semi×ÊÁÏ/SEMI E30 - 0200.pdf
Binary files differ
Document/semi×ÊÁÏ/semi×ÊÁÏ/SEMI E37 - 0999_1_35_translate.pdf
Binary files differ
Document/semi×ÊÁÏ/semi×ÊÁÏ/SEMI E84ÎÕÊÖ.pdf
Binary files differ
Document/semi×ÊÁÏ/semi×ÊÁÏ/semi±ê×¼ºÏ¼¯.pdf
Binary files differ
SourceCode/Bond/BoounionPLC/AlarmMonitor.cpp
@@ -236,11 +236,13 @@
void CAlarmMonitor::addAlarmToHistoryRecord(CAlarm* pAlarm)
{
    // åŠ å…¥æ•°æ®åº“
    /*
    AlarmManager::getInstance().addAlarm(
        std::to_string(pAlarm->getId()).c_str(),
        getAlarmText(pAlarm->getId()),
        CToolUnits::timeToString2(pAlarm->getOnTime()).c_str(),
        CToolUnits::timeToString2(pAlarm->getOffTime()).c_str());
        */
}
BOOL CAlarmMonitor::addAlarming(CAlarm* pAlarm)
SourceCode/Bond/BoounionPLC/AxisDetailSettingsDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,633 @@
// AxisDetailSettingsDlg.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BoounionPLC.h"
#include "AxisDetailSettingsDlg.h"
#include "NewCellTypes/GridCellCheck.h"
// CAxisDetailSettingsDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CAxisDetailSettingsDlg, CBaseDlg)
CAxisDetailSettingsDlg::CAxisDetailSettingsDlg(AxisManager* pAxisManager, int nAxisNO, CWnd* pParent /*=nullptr*/)
    : CBaseDlg(IDD_DIALOG_AXIS_DETAIL_SETTINGS, pParent)
{
    CPLC* pPLC = theApp.m_model.getCurrentPlc();
    if (pPLC != nullptr && pAxisManager != nullptr) {
        m_pPLC = pPLC;
        m_pAxisManager = pAxisManager;
    } else {
        m_pPLC = nullptr;
        m_pAxisManager = nullptr;
    }
    m_nAxisNO = nAxisNO;
}
CAxisDetailSettingsDlg::~CAxisDetailSettingsDlg()
{
}
void CAxisDetailSettingsDlg::InitAnchorPontManager()
{
    if (m_grid.GetSafeHwnd() == NULL)
        return;
    int nRows = 1;
    int nCols = 6;
    int nFixRows = 1;
    int nFixCols = 0;
    int nRowIdx = 0;
    int nColIdx = 0;
    m_grid.DeleteAllItems();
    m_grid.SetVirtualMode(FALSE);
    m_grid.GetDefaultCell(TRUE, FALSE)->SetBackClr(g_nGridFixCellColor); // è®¾ç½®å›ºå®šè¡ŒèƒŒæ™¯è‰²
    m_grid.GetDefaultCell(FALSE, TRUE)->SetBackClr(g_nGridFixCellColor); // è®¾ç½®å›ºå®šåˆ—背景色
    m_grid.GetDefaultCell(FALSE, FALSE)->SetBackClr(g_nGridCellColor);     // è®¾ç½®å•元格背景色
    m_grid.SetFixedTextColor(g_nGridFixFontColor);                         // è®¾ç½®å›ºå®šè¡Œåˆ—字体颜色
    m_grid.SetRowCount(nRows);
    m_grid.SetColumnCount(nCols);
    m_grid.SetFixedRowCount(nFixRows);
    m_grid.SetFixedColumnCount(nFixCols);
    // Col
    m_grid.SetColumnWidth(nColIdx, 10);
    m_grid.SetItemText(nRowIdx, nColIdx++, _T("No."));
    m_grid.SetColumnWidth(nColIdx, 10);
    m_grid.SetItemText(nRowIdx, nColIdx++, _T("激活"));
    m_grid.SetColumnWidth(nColIdx, 50);
    m_grid.SetItemText(nRowIdx, nColIdx++, _T("最小值"));
    m_grid.SetColumnWidth(nColIdx, 50);
    m_grid.SetItemText(nRowIdx, nColIdx++, _T("当前值"));
    m_grid.SetColumnWidth(nColIdx, 50);
    m_grid.SetItemText(nRowIdx, nColIdx++, _T("最大值"));
    m_grid.SetColumnWidth(nColIdx, 120);
    m_grid.SetItemText(nRowIdx, nColIdx++, _T("描述"));
    m_grid.SetFixedRowSelection(FALSE);
    m_grid.SetFixedColumnSelection(FALSE);
    m_grid.SetEditable(TRUE);
    m_grid.SetRowResize(FALSE);
    m_grid.SetColumnResize(TRUE);
    m_grid.ExpandColumnsToFit(TRUE);
    m_grid.SetListMode(TRUE);                    // å¯ç”¨åˆ—表模式
    m_grid.EnableSelection(TRUE);                // å¯ç”¨é€‰æ‹©
    m_grid.SetSingleRowSelection(TRUE);    // è‡ªåŠ¨æ•´è¡Œé«˜äº®ï¼ˆé™åˆ¶ä¸ºå•è¡Œé€‰æ‹©ï¼‰
    m_grid.ExpandLastColumn();                    // æœ€åŽä¸€åˆ—填充网格
    FillAnchorPontManager();
}
void CAxisDetailSettingsDlg::FillAnchorPontManager()
{
    int nRowIndex = 1;
    auto axisDetails = m_pAxisManager->GetAxis(m_nAxisNO);
    int nPositionsSize = (int)axisDetails.positions.size();
    // æ¸…除数据行,保留表头
    for (int i = 1; i < m_grid.GetRowCount(); i++) {
        m_grid.DeleteRow(i);
    }
    // è®¾ç½®è¡¨æ ¼è¡Œæ•°
    m_grid.SetRowCount(axisDetails.positioningPointCount + 1);
    auto SetCellText = [this](int nRow, int nCol, const CString& strText, UINT nState = GVIS_READONLY) {
        m_grid.SetItemText(nRow, nCol, strText);
        m_grid.SetItemState(nRow, nCol, nState);
    };
    auto FormatFloatToString = [](double dValue) -> CString {
        CString strText;
        strText.Format(_T("%.3f"), dValue);
        return strText;
    };
    for (int nIndex = 0; nIndex < axisDetails.positioningPointCount; nIndex++) {
        m_grid.SetItemState(nIndex, 0, GVIS_READONLY); // åºå·åˆ—设置只读
        SetCellText(nRowIndex, 0, CString(std::to_string(nRowIndex).c_str()));
        if (nIndex >= nPositionsSize) {
            // æ·»åŠ æ–°è¡Œçš„é»˜è®¤å€¼
            if (m_grid.SetCellType(nRowIndex, 1, RUNTIME_CLASS(CGridCellCheck))) {
                auto* pCell = static_cast<CGridCellCheck*>(m_grid.GetCell(nRowIndex, 1));
                pCell->SetCheck(TRUE);
            }
            SetCellText(nRowIndex, 2, FormatFloatToString(0.0), GVIS_MODIFIED);
            SetCellText(nRowIndex, 3, FormatFloatToString(1.0), GVIS_MODIFIED);
            SetCellText(nRowIndex, 4, FormatFloatToString(10.0), GVIS_MODIFIED);
            SetCellText(nRowIndex, 5, CString(_T("Position ")) + CString(std::to_string(nIndex + 1).c_str()), GVIS_MODIFIED);
        }
        else {
            const auto& enPosition = axisDetails.positions[nIndex];
            if (m_grid.SetCellType(nRowIndex, 1, RUNTIME_CLASS(CGridCellCheck))) {
                auto* pCell = static_cast<CGridCellCheck*>(m_grid.GetCell(nRowIndex, 1));
                pCell->SetCheck(enPosition.isEnable);
            }
            UINT nCellState = enPosition.isEnable ? GVIS_MODIFIED : GVIS_READONLY;
            SetCellText(nRowIndex, 2, FormatFloatToString(enPosition.range.minValue), nCellState);
            SetCellText(nRowIndex, 3, FormatFloatToString(enPosition.range.currentValue), nCellState);
            SetCellText(nRowIndex, 4, FormatFloatToString(enPosition.range.maxValue), nCellState);
            SetCellText(nRowIndex, 5, CString(enPosition.description.c_str()), nCellState);
        }
        nRowIndex++;
    }
    m_grid.ExpandColumnsToFit(FALSE);
    m_grid.ExpandLastColumn();
    m_grid.Invalidate();
    m_grid.UpdateWindow();
}
void CAxisDetailSettingsDlg::UpdateAxisDetailSettings()
{
    // èŽ·å–è½´æ•°æ®
    auto axisDetails = m_pAxisManager->GetAxis(m_nAxisNO);
    auto formatDouble = [](double value) -> CString {
        CString str;
        str.Format(_T("%.3f"), value);
        return str;
    };
    auto formatInt = [](int value) -> CString {
        CString str;
        str.Format(_T("%d"), value);
        return str;
    };
    m_staticAxisNO.SetWindowText(CString(axisDetails.number.c_str()));                                // è½´ç¼–号
    m_staticAxisDescription.SetWindowText(CString(axisDetails.description.c_str()));                // è½´æè¿°
    m_staticStartAddress.SetWindowText(CString(axisDetails.startAddress.c_str()));                    // èµ·å§‹åœ°å€
    // å®šä½ç‚¹æ•°
    GetDlgItem(IDC_EDIT_AXIS_POSITIONING_POINTS)->SetWindowText(formatInt(axisDetails.positioningPointCount));
    // å¾®åŠ¨é‡
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM_MIN)->SetWindowText(formatDouble(axisDetails.jogDistance.minValue));
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM)->SetWindowText(formatDouble(axisDetails.jogDistance.currentValue));
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM_MAX)->SetWindowText(formatDouble(axisDetails.jogDistance.maxValue));
    // æ‰‹åŠ¨é€Ÿåº¦
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_POS_MIN)->SetWindowText(formatDouble(axisDetails.manualSpeed.minValue));
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_POS)->SetWindowText(formatDouble(axisDetails.manualSpeed.currentValue));
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_POS_MAX)->SetWindowText(formatDouble(axisDetails.manualSpeed.maxValue));
    // è‡ªåŠ¨é€Ÿåº¦
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED_MIN)->SetWindowText(formatDouble(axisDetails.autoSpeed.minValue));
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED)->SetWindowText(formatDouble(axisDetails.autoSpeed.currentValue));
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED_MAX)->SetWindowText(formatDouble(axisDetails.autoSpeed.maxValue));
    // åŠ é€Ÿæ—¶é—´
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME_MIN)->SetWindowText(formatDouble(axisDetails.accelerationTime.minValue));
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME)->SetWindowText(formatDouble(axisDetails.accelerationTime.currentValue));
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME_MAX)->SetWindowText(formatDouble(axisDetails.accelerationTime.maxValue));
    // å‡é€Ÿæ—¶é—´
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME_MIN)->SetWindowText(formatDouble(axisDetails.decelerationTime.minValue));
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME)->SetWindowText(formatDouble(axisDetails.decelerationTime.currentValue));
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME_MAX)->SetWindowText(formatDouble(axisDetails.decelerationTime.maxValue));
}
bool CAxisDetailSettingsDlg::ParsePLCAddress(const CString& address, MC::SOFT_COMPONENT& component, int& addr)
{
    if (address.GetLength() < 2) {
        return false;
    }
    // æå–组件类型(第一个字符)
    TCHAR componentChar = address[0];
    if (address.Left(2) == _T("ZR")) {
        component = MC::SOFT_COMPONENT::ZR;
        // æå–数字部分(去除ZR前缀)
        CString numericAddress = address.Mid(2);
        addr = _ttoi(numericAddress);
        return addr != 0 || numericAddress.CompareNoCase(_T("0")) == 0;  // å¦‚果是 "0",也认为有效
    }
    // å¯¹äºŽå…¶ä»–组件,按照常规规则处理
    CString hexAddress = address.Mid(1);
    switch (componentChar) {
    case 'D':
        component = MC::SOFT_COMPONENT::D;
        addr = _ttoi(hexAddress);
        break;
    case 'M':
        component = MC::SOFT_COMPONENT::M;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'X':
        component = MC::SOFT_COMPONENT::X;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'Y':
        component = MC::SOFT_COMPONENT::Y;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'W':
        component = MC::SOFT_COMPONENT::W;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'L':
        component = MC::SOFT_COMPONENT::L;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'S':
        component = MC::SOFT_COMPONENT::S;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'B':
        component = MC::SOFT_COMPONENT::B;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'F':
        component = MC::SOFT_COMPONENT::F;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    default:
        return false;
    }
    // æ£€æŸ¥åœ°å€æ˜¯å¦æœ‰æ•ˆ
    if (addr == 0 && hexAddress.CompareNoCase(_T("0")) != 0) {
        return false;
    }
    return true;
}
void CAxisDetailSettingsDlg::WriteAxisDataToPLC(int nAxisId)
{
    // èŽ·å–è½´æ•°æ®
    AxisInfo axisData = m_pAxisManager->GetAxis(nAxisId);
    MC::SOFT_COMPONENT enComponent;
    int nStartAddress, nSize;
    if (!ParsePLCAddress(CString(axisData.startAddress.c_str()), enComponent, nStartAddress)) {
        AfxMessageBox(_T("无效的起始地址!"));
    }
    // å†™å…¥å¾®åŠ¨é‡
    m_pPLC->writeWord(enComponent, nStartAddress + 81, (int)(axisData.jogDistance.currentValue * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: å¾®åŠ¨é‡, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: å¾®åŠ¨é‡, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥å®šä½ç‚¹æ•°
    m_pPLC->writeWord(enComponent, nStartAddress + 99, (int)(axisData.positioningPointCount), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: å®šä½ç‚¹æ•°, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: å®šä½ç‚¹æ•°, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥æ‰‹åŠ¨é€Ÿåº¦
    m_pPLC->writeDWord(enComponent, nStartAddress + 82, (int)(axisData.manualSpeed.currentValue * 1000), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: æ‰‹åŠ¨é€Ÿåº¦, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: æ‰‹åŠ¨é€Ÿåº¦, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥æœ€å¤§æ‰‹åŠ¨é€Ÿåº¦
    m_pPLC->writeDWord(enComponent, nStartAddress + 72, (int)(axisData.manualSpeed.maxValue * 1000), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: æœ€å¤§æ‰‹åŠ¨é€Ÿåº¦, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: æœ€å¤§æ‰‹åŠ¨é€Ÿåº¦, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥è‡ªåŠ¨é€Ÿåº¦
    m_pPLC->writeDWord(enComponent, nStartAddress + 84, (int)(axisData.autoSpeed.currentValue * 1000), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: è‡ªåŠ¨é€Ÿåº¦, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: è‡ªåŠ¨é€Ÿåº¦, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥æœ€å¤§è‡ªåŠ¨é€Ÿåº¦
    m_pPLC->writeDWord(enComponent, nStartAddress + 60, (int)(axisData.autoSpeed.maxValue * 1000), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: æœ€å¤§è‡ªåŠ¨é€Ÿåº¦, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: æœ€å¤§è‡ªåŠ¨é€Ÿåº¦, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥åŠ é€Ÿæ—¶é—´
    m_pPLC->writeDWord(enComponent, nStartAddress + 62, (int)(axisData.accelerationTime.currentValue * 1000), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: åŠ é€Ÿæ—¶é—´, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: åŠ é€Ÿæ—¶é—´, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥å‡é€Ÿæ—¶é—´
    m_pPLC->writeDWord(enComponent, nStartAddress + 64, (int)(axisData.decelerationTime.currentValue * 1000), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: å‡é€Ÿæ—¶é—´, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: å‡é€Ÿæ—¶é—´, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥å®šä½ç‚¹æ•°æ®
    {
        char szWrite[100] = { 0 };
        auto writeIntToBuffer = [&](int value, int nWriteIndex) {
            if (nWriteIndex + 4 <= sizeof(szWrite)) {
                // å°ç«¯
                szWrite[nWriteIndex] = static_cast<char>(value & 0xFF);             // ä½Žå­—节
                szWrite[nWriteIndex + 1] = static_cast<char>((value >> 8) & 0xFF);  // æ¬¡ä½Žå­—节
                szWrite[nWriteIndex + 2] = static_cast<char>((value >> 16) & 0xFF); // æ¬¡é«˜å­—节
                szWrite[nWriteIndex + 3] = static_cast<char>((value >> 24) & 0xFF); // é«˜å­—节
            }
        };
        nSize = sizeof(szWrite);
        int nAddress = nStartAddress + 100;
        for (int i = 0; i < axisData.positions.size(); ++i) {
            const auto& position = axisData.positions[i];
            writeIntToBuffer(static_cast<int>(position.range.currentValue * 1000),  (i * 4));
        }
        m_pPLC->writeData(enComponent, nAddress, szWrite, nSize, [nAddress, &szWrite](IMcChannel* pChannel, int nAddr, DWORD nValue, int nFlag) {
            if (nFlag == 0) {
                TRACE("操作成功:地址=%d,值=%s\n", nAddress, szWrite);
            }
            else {
                TRACE("操作失败:地址=%d,错误码=%d\n", nAddress, nFlag);
            }
        });
    }
    // å†™å…¥å®šä½ç‚¹ä¸Šä¸‹é™
    {
        char szWrite[200] = { 0 };
        auto writeIntToBuffer = [&](int value, int nWriteIndex) {
            if (nWriteIndex + 4 <= sizeof(szWrite)) {
                // å°ç«¯
                szWrite[nWriteIndex] = static_cast<char>(value & 0xFF);             // ä½Žå­—节
                szWrite[nWriteIndex + 1] = static_cast<char>((value >> 8) & 0xFF);  // æ¬¡ä½Žå­—节
                szWrite[nWriteIndex + 2] = static_cast<char>((value >> 16) & 0xFF); // æ¬¡é«˜å­—节
                szWrite[nWriteIndex + 3] = static_cast<char>((value >> 24) & 0xFF); // é«˜å­—节
            }
        };
        nSize = sizeof(szWrite);
        int nAddress = nStartAddress + 200;
        int nIndex = 0;
        for (int i = 0; i < axisData.positions.size(); ++i) {
            const auto& position = axisData.positions[i];
            writeIntToBuffer(static_cast<int>(position.range.minValue * 1000), (nIndex * 4));
            writeIntToBuffer(static_cast<int>(position.range.maxValue * 1000), ((nIndex + 1) * 4));
            nIndex += 2;
        }
        m_pPLC->writeData(enComponent, nAddress, szWrite, nSize, [nAddress, &szWrite](IMcChannel* pChannel, int nAddr, DWORD nValue, int nFlag) {
            if (nFlag == 0) {
                TRACE("操作成功:地址=%d,值=%s\n", nAddress, szWrite);
            }
            else {
                TRACE("操作失败:地址=%d,错误码=%d\n", nAddress, nFlag);
            }
        });
    }
}
void CAxisDetailSettingsDlg::DoDataExchange(CDataExchange* pDX)
{
    CBaseDlg::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_STATIC_AXIS_NUMBER, m_staticAxisNO);
    DDX_Control(pDX, IDC_STATIC_AXIS_DESCRIP, m_staticAxisDescription);
    DDX_Control(pDX, IDC_STATIC_START_ADDRESS, m_staticStartAddress);
    DDX_Control(pDX, IDC_CUSTOM_AXIS_ANCHOR_POINT, m_grid);
}
BEGIN_MESSAGE_MAP(CAxisDetailSettingsDlg, CBaseDlg)
    ON_NOTIFY(NM_CLICK, IDC_CUSTOM_AXIS_ANCHOR_POINT, &CAxisDetailSettingsDlg::OnGridItemChanged)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_DETAIL_SETTINGS_SAVE, &CAxisDetailSettingsDlg::OnBnClickedButtonAxisDetailSettingsSave)
    ON_BN_CLICKED(IDC_BUTTON_SET_AXIS_POSITIONING_POINTS, &CAxisDetailSettingsDlg::OnBnClickedButtonSetAxisPositioningPoints)
END_MESSAGE_MAP()
// CAxisDetailSettingsDlg æ¶ˆæ¯å¤„理程序
BOOL CAxisDetailSettingsDlg::OnInitDialog()
{
    CBaseDlg::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    if (m_pPLC == nullptr || !m_pPLC->isConnected()) {
        AfxMessageBox(_T("PLC æœªè¿žæŽ¥ï¼"));
        return FALSE;
    }
    if (m_pAxisManager == nullptr) {
        AfxMessageBox(_T("轴管理器未加载!"));
        return FALSE;
    }
    CString strTitle;
    strTitle.Format(_T("轴细部设定(PLC: %s)"), m_pPLC->getName().c_str());
    SetWindowText(strTitle);
    // èŽ·å–è½´æ•°æ®
    auto axisDetails = m_pAxisManager->GetAxis(m_nAxisNO);
    if (axisDetails.id == -1) {
        CString strMsg;
        strMsg.Format(_T("è½´ [%d] ä¸å­˜åœ¨ï¼"), m_nAxisNO);
        AfxMessageBox(strMsg);
        return FALSE;
    }
    UpdateAxisDetailSettings();
    InitAnchorPontManager();
    return TRUE;  // return TRUE unless you set the focus to a control
    // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
void CAxisDetailSettingsDlg::OnGridItemChanged(NMHDR* pNotifyStruct, LRESULT* pResult)
{
    NM_GRIDVIEW* pItem = (NM_GRIDVIEW*)pNotifyStruct;
    int nRow = pItem->iRow;
    int nCol = pItem->iColumn;
    // å¤„理复选框状态变化
    if (nCol == 1) {
        // èŽ·å–å¤é€‰æ¡†çš„å½“å‰çŠ¶æ€
        CGridCellCheck* pCell = static_cast<CGridCellCheck*>(m_grid.GetCell(nRow, nCol));
        BOOL bChecked = pCell->GetCheck();
        // å¤„理复选框状态变化
        m_grid.SetItemState(nRow, 2, bChecked ? GVIS_MODIFIED : GVIS_READONLY);
        m_grid.SetItemState(nRow, 3, bChecked ? GVIS_MODIFIED : GVIS_READONLY);
        m_grid.SetItemState(nRow, 4, bChecked ? GVIS_MODIFIED : GVIS_READONLY);
        m_grid.SetItemState(nRow, 5, bChecked ? GVIS_MODIFIED : GVIS_READONLY);
    }
    *pResult = 0;
}
void CAxisDetailSettingsDlg::OnBnClickedButtonAxisDetailSettingsSave()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    // èŽ·å–è½´æ•°æ®
    auto& axisDetails = m_pAxisManager->GetAxis(m_nAxisNO);
    // è½´ç¼–号、描述和起始地址
    CString strAxisNo, strAxisDesc, strStartAddr;
    m_staticAxisNO.GetWindowText(strAxisNo);
    m_staticAxisDescription.GetWindowText(strAxisDesc);
    m_staticStartAddress.GetWindowText(strStartAddr);
    axisDetails.number = std::string(CT2A(strAxisNo));
    axisDetails.description = std::string(CT2A(strAxisDesc));
    axisDetails.startAddress = std::string(CT2A(strStartAddr));
    // å®šä½ç‚¹æ•°
    CString strPosCount;
    GetDlgItem(IDC_EDIT_AXIS_POSITIONING_POINTS)->GetWindowText(strPosCount);
    axisDetails.positioningPointCount = _ttoi(strPosCount);
    // å¾®åŠ¨é‡
    CString strJogDistanceMin, strJogDistanceCur, strJogDistanceMax;
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM_MIN)->GetWindowText(strJogDistanceMin);
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM)->GetWindowText(strJogDistanceCur);
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM_MAX)->GetWindowText(strJogDistanceMax);
    axisDetails.jogDistance.minValue = _ttof(strJogDistanceMin);
    axisDetails.jogDistance.currentValue = _ttof(strJogDistanceCur);
    axisDetails.jogDistance.maxValue = _ttof(strJogDistanceMax);
    // æ‰‹åŠ¨é€Ÿåº¦
    CString strManualSpeedMin, strManualSpeedCur, strManualSpeedMax;
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_POS_MIN)->GetWindowText(strManualSpeedMin);
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_POS)->GetWindowText(strManualSpeedCur);
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_POS_MAX)->GetWindowText(strManualSpeedMax);
    axisDetails.manualSpeed.minValue = _ttof(strManualSpeedMin);
    axisDetails.manualSpeed.currentValue = _ttof(strManualSpeedCur);
    axisDetails.manualSpeed.maxValue = _ttof(strManualSpeedMax);
    // è‡ªåŠ¨é€Ÿåº¦
    CString strAutoSpeedMin, strAutoSpeedCur, strAutoSpeedMax;
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED_MIN)->GetWindowText(strAutoSpeedMin);
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED)->GetWindowText(strAutoSpeedCur);
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED_MAX)->GetWindowText(strAutoSpeedMax);
    axisDetails.autoSpeed.minValue = _ttof(strAutoSpeedMin);
    axisDetails.autoSpeed.currentValue = _ttof(strAutoSpeedCur);
    axisDetails.autoSpeed.maxValue = _ttof(strAutoSpeedMax);
    // åŠ é€Ÿæ—¶é—´
    CString strAcceTimeMin, strAcceTimeCur, strAcceTimeMax;
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME_MIN)->GetWindowText(strAcceTimeMin);
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME)->GetWindowText(strAcceTimeCur);
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME_MAX)->GetWindowText(strAcceTimeMax);
    axisDetails.accelerationTime.minValue = _ttof(strAcceTimeMin);
    axisDetails.accelerationTime.currentValue = _ttof(strAcceTimeCur);
    axisDetails.accelerationTime.maxValue = _ttof(strAcceTimeMax);
    // å‡é€Ÿæ—¶é—´
    CString strDeceTimeMin, strDeceTimeCur, strDeceTimeMax;
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME_MIN)->GetWindowText(strDeceTimeMin);
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME)->GetWindowText(strDeceTimeCur);
    GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME_MAX)->GetWindowText(strDeceTimeMax);
    axisDetails.decelerationTime.minValue = _ttof(strDeceTimeMin);
    axisDetails.decelerationTime.currentValue = _ttof(strDeceTimeCur);
    axisDetails.decelerationTime.maxValue = _ttof(strDeceTimeMax);
    // å¦‚æžœ positioningPointCount å’Œ positions.size() ä¸åŒï¼Œåˆ™è°ƒæ•´å¤§å°
    if (axisDetails.positioningPointCount != (int)axisDetails.positions.size()) {
        axisDetails.positions.resize(axisDetails.positioningPointCount);
    }
    // æ›´æ–°è¡¨æ ¼ä¸­çš„定位点数据
    for (int i = 0; i < axisDetails.positioningPointCount; i++) {
        auto& enPosition = axisDetails.positions[i];
        // ä½¿èƒ½çŠ¶æ€
        BOOL bIsChecked = ((CGridCellCheck*)m_grid.GetCell(i + 1, 1))->GetCheck();
        enPosition.isEnable = bIsChecked;
        // æœ€å°å€¼ã€å½“前值和最大值
        CString strMin, strCur, strMax;
        strMin = m_grid.GetItemText(i + 1, 2);
        strCur = m_grid.GetItemText(i + 1, 3);
        strMax = m_grid.GetItemText(i + 1, 4);
        enPosition.range.minValue = _ttof(strMin);
        enPosition.range.currentValue = _ttof(strCur);
        enPosition.range.maxValue = _ttof(strMax);
        // æè¿°
        CString strDesc;
        strDesc = m_grid.GetItemText(i + 1, 5);
        enPosition.description = std::string(CT2A(strDesc));
    }
    m_pAxisManager->UpdateAxis(axisDetails);
    // ä¿å­˜è½´æ•°æ®åˆ°æ–‡ä»¶
    CString cstrMessage;
    if (m_pAxisManager->SaveAxis(m_pPLC->getName())) {
        WriteAxisDataToPLC(m_nAxisNO);
        cstrMessage.Format(_T("保存轴 [%d] ç»†éƒ¨å‚数成功!"), m_nAxisNO);
    }
    else {
        cstrMessage.Format(_T("保存轴 [%d] ç»†éƒ¨å‚数失败!"), m_nAxisNO);
    }
    AfxMessageBox(cstrMessage);
}
void CAxisDetailSettingsDlg::OnBnClickedButtonSetAxisPositioningPoints()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    CString strPosCount;
    GetDlgItem(IDC_EDIT_AXIS_POSITIONING_POINTS)->GetWindowText(strPosCount);
    if (strPosCount.IsEmpty()) {
        AfxMessageBox(_T("请输入定位点数!"));
        return;
    }
    short nCount = _ttoi(strPosCount);
    if (nCount < 1 || nCount > 25) {
        AfxMessageBox(_T("范围在1-25之间!"));
        return;
    }
    AxisInfo axisDetails = m_pAxisManager->GetAxis(m_nAxisNO);
    axisDetails.positioningPointCount = _ttoi(strPosCount);
    // æ›´æ–° AxisManager ä¸­çš„轴数据
    m_pAxisManager->UpdateAxis(axisDetails);
    FillAnchorPontManager();
}
SourceCode/Bond/BoounionPLC/AxisDetailSettingsDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
#pragma once
#include "afxdialogex.h"
#include "GridCtrl.h"
#include "CBaseDlg.h"
#include "PLC.h"
#include "AxisManager.h"
// CAxisDetailSettingsDlg å¯¹è¯æ¡†
class CAxisDetailSettingsDlg : public CBaseDlg
{
    DECLARE_DYNAMIC(CAxisDetailSettingsDlg)
public:
    CAxisDetailSettingsDlg(AxisManager* pAxisManager, int nAxisNO, CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CAxisDetailSettingsDlg();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_AXIS_DETAIL_SETTINGS };
#endif
private:
    void InitAnchorPontManager();
    void FillAnchorPontManager();
    void UpdateAxisDetailSettings();
    bool ParsePLCAddress(const CString& address, MC::SOFT_COMPONENT& component, int& addr);
    void WriteAxisDataToPLC(int nAxisId);
private:
    CPLC* m_pPLC;
    int m_nAxisNO;
    // è½´ç®¡ç†å™¨
    AxisManager* m_pAxisManager;
    // æŽ§ä»¶
    CStatic m_staticAxisNO, m_staticAxisDescription, m_staticStartAddress;
    CGridCtrl m_grid;
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    virtual BOOL OnInitDialog();
    afx_msg void OnGridItemChanged(NMHDR* pNotifyStruct, LRESULT* pResult);
    afx_msg void OnBnClickedButtonAxisDetailSettingsSave();
    afx_msg void OnBnClickedButtonSetAxisPositioningPoints();
    DECLARE_MESSAGE_MAP()
};
SourceCode/Bond/BoounionPLC/AxisSettingsDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1383 @@
// AxisSettingsDlg.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "BoounionPLC.h"
#include "afxdialogex.h"
#include "AxisSettingsDlg.h"
#include "AxisDetailSettingsDlg.h"
#include "ToolUnits.h"
#include <cctype>
#define COLOR_GREEN_ON    RGB(0, 255, 0)  // æ­£å¸¸çŠ¶æ€ç»¿è‰²
#define COLOR_GREEN_OFF   RGB(0, 180, 0)  // åç»¿çŠ¶æ€
#define COLOR_RED         RGB(255, 0, 0)  // é”™è¯¯çŠ¶æ€çº¢è‰²
#define TIMER_INIT                    1
#define TIMER_READ_PLC_DATA            2
#define ID_MSG_UPDATA_DATA_TO_UI    WM_USER + 101
// CAxisSettingsDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CAxisSettingsDlg, CBaseDlg)
CAxisSettingsDlg::CAxisSettingsDlg(CWnd* pParent /*=nullptr*/)
    : CBaseDlg(IDD_DIALOG_AXIS_SETTINGS, pParent)
{
    CPLC* pPLC = theApp.m_model.getCurrentPlc();
    if (pPLC != nullptr) {
        m_pPLC = pPLC;
        m_pAxisManager = new AxisManager();
        m_pAxisManager->LoadAxis(pPLC->getName());
    }
    m_bSEV = FALSE;
    m_fCurPos = 0.0;
    m_fManualSpeed = 0.0;
    m_fAutoSpeed = 0.0;
    m_fPrm = 0.0;
    m_nLoad = 0;
    m_nErrCode = 0;
    m_nAlarmCode = 0;
    m_bFLS = FALSE;
    m_bDOG = FALSE;
    m_bRLS = FALSE;
    m_bReady = FALSE;
    m_bBusy = FALSE;
    m_bErr = FALSE;
    for (int i = 0; i < BTN_MAX; i++) {
        m_pBlBtns[i] = new CBlButton();
    }
    for (int i = 0; i < EDIT_MAX; i++) {
        m_pRegexEdit[i] = new CRegexEdit();
    }
    for (int i = 0; i < LABEL_MAX; i++) {
        m_pBlLabels[i] = new CBLLabel();
    }
    m_nBtnsFlashState6 = 0;
    m_nBtnsFlashState8 = 0;
}
CAxisSettingsDlg::~CAxisSettingsDlg()
{
    for (int i = 0; i < BTN_MAX; i++) {
        delete m_pBlBtns[i];
    }
    for (int i = 0; i < EDIT_MAX; i++) {
        delete m_pRegexEdit[i];
    }
    for (int i = 0; i < LABEL_MAX; i++) {
        delete m_pBlLabels[i];
    }
    if (m_pAxisManager != nullptr) {
        delete m_pAxisManager;
        m_pAxisManager = nullptr;
    }
}
void CAxisSettingsDlg::DoDataExchange(CDataExchange* pDX)
{
    CBaseDlg::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_COMBO_AXIS_NAME, m_comboAxisNO);
    DDX_Control(pDX, IDC_STATIC_AXIS_NUMBER, m_staticAxisNO);
    DDX_Control(pDX, IDC_STATIC_AXIS_DESCRIP, m_staticAxisDescription);
    DDX_Control(pDX, IDC_STATIC_START_ADDRESS, m_staticStartAddress);
}
UINT CAxisSettingsDlg::FindIDByName(const CString& strControlID)
{
    // å°†èµ„源文件中定义的控件名称和 ID åŠ è½½åˆ°ä¸€ä¸ªæ˜ å°„ä¸­
    static const std::map<CString, UINT> controlIdMap = {
        {"IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP1", IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP1},
        {"IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP2", IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP2},
        {"IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP3", IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP3},
        {"IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP4", IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP4},
        {"IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP5", IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP5},
        {"IDC_EDIT_AXIS_ANCHOR_POINT1", IDC_EDIT_AXIS_ANCHOR_POINT1},
        {"IDC_EDIT_AXIS_ANCHOR_POINT2", IDC_EDIT_AXIS_ANCHOR_POINT2},
        {"IDC_EDIT_AXIS_ANCHOR_POINT3", IDC_EDIT_AXIS_ANCHOR_POINT3},
        {"IDC_EDIT_AXIS_ANCHOR_POINT4", IDC_EDIT_AXIS_ANCHOR_POINT4},
        {"IDC_EDIT_AXIS_ANCHOR_POINT5", IDC_EDIT_AXIS_ANCHOR_POINT5}
        // å¯ä»¥ç»§ç»­æ·»åŠ å…¶ä»–æŽ§ä»¶åç§°å’Œ ID
    };
    // æŸ¥æ‰¾æŽ§ä»¶åç§°æ˜¯å¦åœ¨æ˜ å°„中
    auto it = controlIdMap.find(strControlID);
    if (it != controlIdMap.end()) {
        return it->second;
    }
    return 0;
}
void CAxisSettingsDlg::AdjustLabelFont(CBLLabel& label)
{
    if (label.m_hWnd == nullptr) {
        return;
    }
    // èŽ·å–æŽ§ä»¶çš„çŸ©å½¢åŒºåŸŸ
    CRect rect;
    label.GetClientRect(&rect);
    // åŠ¨æ€è®¡ç®—å­—ä½“å¤§å°ï¼ŒåŸºäºŽæŽ§ä»¶çš„é«˜åº¦
    int fontSize = rect.Height() / 2; // æŽ§ä»¶é«˜åº¦çš„一半作为字体大小
    if (fontSize < 8) fontSize = 8;   // æœ€å°å­—体大小
    if (fontSize > 20) fontSize = 20; // æœ€å¤§å­—体大小
    // è®¾ç½®å­—体大小
    label.SetFontSize(fontSize);
    // åˆ·æ–°æŽ§ä»¶æ˜¾ç¤º
    label.Invalidate();
    label.UpdateWindow();
}
void CAxisSettingsDlg::SetLabelColor(CBLLabel& label, COLORREF color)
{
    label.SetBkColor(color);
    label.Invalidate();              // æ ‡è®°åŒºåŸŸæ— æ•ˆ
    label.UpdateWindow();            // ç«‹å³åˆ·æ–°
}
void CAxisSettingsDlg::SetLabelColorBasedOnState(CBLLabel& label, BOOL bState, COLORREF colorTrue, COLORREF colorFalse) {
    SetLabelColor(label, bState ? colorTrue : colorFalse);
}
void CAxisSettingsDlg::UpdateLabels() {
    SetLabelColorBasedOnState(*m_pBlLabels[LABEL_FLS], m_bFLS, COLOR_GREEN_ON, COLOR_GREEN_OFF);
    SetLabelColorBasedOnState(*m_pBlLabels[LABEL_DOG], m_bDOG, COLOR_GREEN_ON, COLOR_GREEN_OFF);
    SetLabelColorBasedOnState(*m_pBlLabels[LABEL_RLS], m_bRLS, COLOR_GREEN_ON, COLOR_GREEN_OFF);
    SetLabelColorBasedOnState(*m_pBlLabels[LABEL_READY], m_bReady, COLOR_GREEN_ON, COLOR_GREEN_OFF);
    SetLabelColorBasedOnState(*m_pBlLabels[LABEL_BUSY], m_bBusy, COLOR_GREEN_ON, COLOR_GREEN_OFF);
    SetLabelColorBasedOnState(*m_pBlLabels[LABEL_ERR], m_bErr, COLOR_RED, COLOR_GREEN_OFF);
}
void CAxisSettingsDlg::UpdateRegexEdit(CRegexEdit* pRegexEdit, const ValueRange& range, const CString& title)
{
    auto formatDouble = [](double value) -> CString {
        CString str;
        str.Format(_T("%.3f"), value);
        return str;
    };
    pRegexEdit->SetWindowText(formatDouble(range.currentValue));
    pRegexEdit->SetRegexType(RegexType::Decimal);
    pRegexEdit->SetValueRange(range.minValue, range.maxValue);
    pRegexEdit->SetInvalidInputCallback([title, range]() {
        CString strError;
        strError.Format(_T("%s的值必须在 %.3f å’Œ %.3f ä¹‹é—´ï¼"), title, range.minValue, range.maxValue);
        AfxMessageBox(strError);
    });
}
void CAxisSettingsDlg::UpdatePageButtonStates()
{
    for (int i = 0; i < AXIS_PAGE_SIZE; ++i) {
        BOOL bSelect = (i + 1 == m_currentPage);
        m_pBlBtns[i]->SetFaceColor(bSelect ?
            BTN_PAGE_FACE_SELECT_COLOR: BTN_PAGE_FACE_NORMAL_COLOR);
        m_pBlBtns[i]->SetTextColor(bSelect ?
            BTN_PAGE_TEXT_SELECT_COLOR : BTN_PAGE_TEXT_NORMAL_COLOR);
    }
}
void CAxisSettingsDlg::HideEditCursor(int nCtrlID)
{
    CEdit* pEdit = (CEdit*)GetDlgItem(nCtrlID);
    if (pEdit && pEdit->GetSafeHwnd()) {
        pEdit->EnableWindow(FALSE); // ç¦ç”¨æŽ§ä»¶
        pEdit->SetReadOnly(TRUE);   // è®¾ç½®ä¸ºåªè¯»
        pEdit->HideCaret();         // éšè—å…‰æ ‡
    }
}
int CAxisSettingsDlg::GetCurrentSelectedAxisID()
{
    int currentIndex = m_comboAxisNO.GetCurSel();
    if (currentIndex == CB_ERR) {
        return -1;
    }
    CString strAxisIDStr;
    m_comboAxisNO.GetLBText(currentIndex, strAxisIDStr);
    return _ttoi(strAxisIDStr);
}
void CAxisSettingsDlg::InitializeAxisIDCombo()
{
    // èŽ·å–æ‰€æœ‰è½´çš„ç¼–å·
    auto axisNumbers = m_pAxisManager->GetAllAxisID();
    if (axisNumbers.empty()) {
        AfxMessageBox(_T("没有找到轴信息!"));
        return;
    }
    // æ¸…空下拉框
    m_comboAxisNO.ResetContent();
    // å¡«å……数据到下拉框
    for (const auto& axisID : axisNumbers) {
        CString axisCString;
        axisCString.Format(_T("%d"), axisID);
        m_comboAxisNO.AddString(axisCString);
    }
    // é»˜è®¤é€‰æ‹©ç¬¬ä¸€é¡¹
    if (m_comboAxisNO.GetCount() > 0) {
        m_comboAxisNO.SetCurSel(0);
    }
}
void CAxisSettingsDlg::RefreshAxisDetails(int nAxisId)
{
    // èŽ·å–è½´æ•°æ®
    auto axisDetails = m_pAxisManager->GetAxis(nAxisId);
    auto formatDouble = [](double value) -> CString {
        CString str;
        str.Format(_T("%.3f"), value);
        return str;
    };
    // æ›´æ–°æŽ§ä»¶æ˜¾ç¤º
    m_staticAxisNO.SetWindowText(CString(axisDetails.number.c_str()));                    // è½´ç¼–号
    m_staticAxisDescription.SetWindowText(CString(axisDetails.description.c_str()));    // è½´æè¿°
    m_staticStartAddress.SetWindowText(CString(axisDetails.startAddress.c_str()));        // èµ·å§‹åœ°å€
    UpdateRegexEdit(m_pRegexEdit[EDIT_MICROMENTUM], axisDetails.jogDistance, _T("微动量"));
    UpdateRegexEdit(m_pRegexEdit[EDIT_MANUAL_SPEED], axisDetails.manualSpeed, _T("手动速度"));
    UpdateRegexEdit(m_pRegexEdit[EDIT_AUTO_SPEED], axisDetails.autoSpeed, _T("自动速度"));
    UpdateRegexEdit(m_pRegexEdit[EDIT_ACCE_TIME], axisDetails.accelerationTime, _T("加速时间"));
    UpdateRegexEdit(m_pRegexEdit[EDIT_DECE_TIME], axisDetails.decelerationTime, _T("减速时间"));
}
void CAxisSettingsDlg::RefreshPositionDetails(int nAxisId, int pageNumber)
{
    // æ¯é¡µæ˜¾ç¤ºçš„定位点数量
    const int pageSize = AXIS_PAGE_SIZE;
    // èŽ·å–å®šä½ç‚¹æ•°æ®
    auto positions = m_pAxisManager->GetPositions(nAxisId, pageNumber, pageSize);
    // åˆ·æ–° UI
    for (int i = 0; i < pageSize; ++i) {
        CString descriptionCtrlName, positionCtrlName;
        descriptionCtrlName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP%d"), i + 1);
        positionCtrlName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT%d"), i + 1);
        UINT descriptionCtrlId = FindIDByName(descriptionCtrlName);
        UINT positionCtrlId = FindIDByName(positionCtrlName);
        CWnd* pDescriptionCtrl = GetDlgItem(descriptionCtrlId);
        CWnd* pPositionCtrl = GetDlgItem(positionCtrlId);
        if (i < positions.size()) {
            const PositionRange& position = positions[i];
            // æ˜¾ç¤ºå®šä½ç‚¹çš„æè¿°
            CString description = CString(position.description.c_str());
            if (pDescriptionCtrl) pDescriptionCtrl->SetWindowText(description);
            // æ˜¾ç¤ºå®šä½ç‚¹çš„当前位置
            CString value;
            value.Format(_T("%.3f"), position.range.currentValue);
            if (pPositionCtrl) {
                pPositionCtrl->SetWindowText(value);
                pPositionCtrl->EnableWindow(position.isEnable);
                if (position.isEnable) {
                    CString strError;
                    strError.Format(_T("定位点%d"), i + 1);
                    UpdateRegexEdit((CRegexEdit*)pPositionCtrl, position.range, strError);
                }
            }
        }
        else {
            // æ¸…空控件内容
            if (pDescriptionCtrl) {
                pDescriptionCtrl->SetWindowText(_T(""));
                pDescriptionCtrl->EnableWindow(FALSE);
            }
            if (pPositionCtrl) {
                pPositionCtrl->SetWindowText(_T(""));
                pPositionCtrl->EnableWindow(FALSE);
            }
        }
    }
}
void CAxisSettingsDlg::UpdatePositionRange(PositionRange& position, int pageNumber, int pageSize, int currentIndex)
{
    // èŽ·å–å½“å‰è¾“å…¥æ¡†ä¸­çš„æ–‡æœ¬
    CString strText;
    GetDlgItem(IDC_EDIT_AXIS_CURR_POS)->GetWindowText(strText);
    if (strText.IsEmpty()) {
        return;
    }
    CString descriptionCtrlName, positionCtrlName;
    descriptionCtrlName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP%d"), currentIndex + 1);
    positionCtrlName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT%d"), currentIndex + 1);
    UINT descriptionCtrlId = FindIDByName(descriptionCtrlName);
    UINT positionCtrlId = FindIDByName(positionCtrlName);
    CWnd* pDescriptionCtrl = GetDlgItem(descriptionCtrlId);
    CWnd* pPositionCtrl = GetDlgItem(positionCtrlId);
    if (pDescriptionCtrl == nullptr || pPositionCtrl == nullptr) {
        return;
    }
    double enteredValue = _ttof(strText);
    double minValue = position.range.minValue;
    double maxValue = position.range.maxValue;
    // åˆ¤æ–­è¾“入的值是否在合法范围内
    if (enteredValue < minValue || enteredValue > maxValue) {
        CString strError;
        strError.Format(_T("定位点的值必须在 %f å’Œ %f ä¹‹é—´ï¼"), minValue, maxValue);
        pDescriptionCtrl->SetWindowText(strError);
    }
    else {
        position.range.currentValue = enteredValue;
        pDescriptionCtrl->SetWindowText(CString(position.description.c_str()));
        pPositionCtrl->SetWindowText(strText);
    }
}
void CAxisSettingsDlg::UpdateAxisSelection(int offset)
{
    int currentIndex = m_comboAxisNO.GetCurSel();
    if (currentIndex == CB_ERR) {
        AfxMessageBox(_T("请选择一个有效的轴编号!"));
        return;
    }
    int newIndex = currentIndex + offset;
    if (newIndex < 0 || newIndex >= m_comboAxisNO.GetCount()) {
        CString error;
        error.Format(_T("已经到达%s一个轴!"), offset < 0 ? _T("上") : _T("下"));
        AfxMessageBox(error);
        return;
    }
    m_comboAxisNO.SetCurSel(newIndex);
    RefreshAxisDetails(newIndex + 1);
    RefreshPositionDetails(newIndex + 1, m_currentPage);
    UpdatePageButtonStates();
}
void CAxisSettingsDlg::UpdateDataFromUI(int nAxisId)
{
    const int pageSize = AXIS_PAGE_SIZE; // æ¯é¡µæ˜¾ç¤º 5 ä¸ªå®šä½ç‚¹
    auto axisData = m_pAxisManager->GetAxis(nAxisId);
    // èŽ·å–ç•Œé¢ä¸Šçš„ä¿®æ”¹å‚æ•°
    CString text;
    m_pRegexEdit[EDIT_MANUAL_SPEED]->GetWindowText(text);
    axisData.manualSpeed.currentValue = _ttof(text);
    m_pRegexEdit[EDIT_AUTO_SPEED]->GetWindowText(text);
    axisData.autoSpeed.currentValue = _ttof(text);
    m_pRegexEdit[EDIT_ACCE_TIME]->GetWindowText(text);
    axisData.accelerationTime.currentValue = _ttof(text);
    m_pRegexEdit[EDIT_DECE_TIME]->GetWindowText(text);
    axisData.decelerationTime.currentValue = _ttof(text);
    m_pRegexEdit[EDIT_MICROMENTUM]->GetWindowText(text);
    axisData.jogDistance.currentValue = _ttof(text);
    // æ›´æ–°å®šä½ç‚¹æ•°æ®
    for (int i = 0; i < pageSize; ++i) {
        int index = (m_currentPage - 1) * pageSize + i;
        if (index < axisData.positions.size()) {
            // æž„建控件名称
            CString descriptionName, positionName;
            descriptionName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP%d"), i + 1);
            positionName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT%d"), i + 1);
            // èŽ·å–æŽ§ä»¶
            CEdit* pDescriptionEdit = (CEdit*)GetDlgItem(FindIDByName(descriptionName));
            CEdit* pPositionEdit = (CEdit*)GetDlgItem(FindIDByName(positionName));
            if (pDescriptionEdit && pPositionEdit) {
                CString description, positionValue;
                // èŽ·å–æŽ§ä»¶ä¸­çš„æ–‡æœ¬
                pDescriptionEdit->GetWindowText(description);
                pPositionEdit->GetWindowText(positionValue);
                // æ›´æ–° AxisManager ä¸­çš„æ•°æ®
                axisData.positions[index].description = CT2A(description);
                axisData.positions[index].range.currentValue = _ttof(positionValue);
            }
        }
    }
    // ä¿å­˜ AxisManager
    m_pAxisManager->UpdateAxis(axisData);
}
void CAxisSettingsDlg::SwitchToPage(int targetPage)
{
    try {
        // å¦‚果当前页面已经是目标页面,直接返回
        if (m_currentPage == targetPage) {
            return;
        }
        // èŽ·å–å½“å‰é€‰ä¸­çš„è½´ ID
        int axisId = GetCurrentSelectedAxisID();
        if (axisId == -1) {
            AfxMessageBox(_T("请选择一个有效的轴编号!"));
            return;
        }
        // æ›´æ–° UI æ•°æ®åˆ°å†…å­˜
        UpdateDataFromUI(axisId);
        // åˆ‡æ¢é¡µé¢
        m_currentPage = targetPage;
        RefreshPositionDetails(axisId, targetPage);
        UpdatePageButtonStates();
    }
    catch (const std::exception& ex) {
        CString errorMsg;
        errorMsg.Format(_T("刷新定位组%d失败:%s"), targetPage, CString(ex.what()));
        AfxMessageBox(errorMsg, MB_ICONERROR);
    }
}
bool CAxisSettingsDlg::ParsePLCAddress(const CString& address, MC::SOFT_COMPONENT& component, int& addr)
{
    if (address.GetLength() < 2) {
        return false;
    }
    // æå–组件类型(第一个字符)
    TCHAR componentChar = address[0];
    if (address.Left(2) == _T("ZR")) {
        component = MC::SOFT_COMPONENT::ZR;
        // æå–数字部分(去除ZR前缀)
        CString numericAddress = address.Mid(2);
        addr = _ttoi(numericAddress);
        return addr != 0 || numericAddress.CompareNoCase(_T("0")) == 0;  // å¦‚果是 "0",也认为有效
    }
    // å¯¹äºŽå…¶ä»–组件,按照常规规则处理
    CString hexAddress = address.Mid(1);
    switch (componentChar) {
    case 'D':
        component = MC::SOFT_COMPONENT::D;
        addr = _ttoi(hexAddress);
        break;
    case 'M':
        component = MC::SOFT_COMPONENT::M;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'X':
        component = MC::SOFT_COMPONENT::X;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'Y':
        component = MC::SOFT_COMPONENT::Y;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'W':
        component = MC::SOFT_COMPONENT::W;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'L':
        component = MC::SOFT_COMPONENT::L;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'S':
        component = MC::SOFT_COMPONENT::S;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'B':
        component = MC::SOFT_COMPONENT::B;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    case 'F':
        component = MC::SOFT_COMPONENT::F;
        addr = _tcstoul(hexAddress, nullptr, 16);
        break;
    default:
        return false;
    }
    // æ£€æŸ¥åœ°å€æ˜¯å¦æœ‰æ•ˆ
    if (addr == 0 && hexAddress.CompareNoCase(_T("0")) != 0) {
        return false;
    }
    return true;
}
void CAxisSettingsDlg::WriteAxisDataToPLC(int nAxisId)
{
    // ä»Ž AxisManager èŽ·å–è½´æ•°æ®
    auto axisData = m_pAxisManager->GetAxis(nAxisId);
    int startAddress;
    MC::SOFT_COMPONENT component;
    if (!ParsePLCAddress(CString(axisData.startAddress.c_str()), component, startAddress)) {
        AfxMessageBox(_T("无效的起始地址!"));
    }
    // å†™å…¥æ‰‹åŠ¨é€Ÿåº¦
    m_pPLC->writeDWord(component, startAddress + 82, (int)axisData.manualSpeed.currentValue * 1000, [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: æ‰‹åŠ¨é€Ÿåº¦, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: æ‰‹åŠ¨é€Ÿåº¦, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥è‡ªåŠ¨é€Ÿåº¦
    m_pPLC->writeDWord(component, startAddress + 84, (int)(axisData.autoSpeed.currentValue * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: è‡ªåŠ¨é€Ÿåº¦, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: è‡ªåŠ¨é€Ÿåº¦, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥åŠ é€Ÿæ—¶é—´, è½¬æ¢ä¸ºæ¯«ç§’
    m_pPLC->writeDWord(component, startAddress + 62, (int)(axisData.accelerationTime.currentValue * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: åŠ é€Ÿæ—¶é—´, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: åŠ é€Ÿæ—¶é—´, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥å‡é€Ÿæ—¶é—´, è½¬æ¢ä¸ºæ¯«ç§’
    m_pPLC->writeDWord(component, startAddress + 64, (int)(axisData.decelerationTime.currentValue * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: å‡é€Ÿæ—¶é—´, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: å‡é€Ÿæ—¶é—´, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥å¾®åŠ¨é‡
    m_pPLC->writeWord(component, startAddress + 81, (int)(axisData.jogDistance.currentValue * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: å¾®åŠ¨é‡, åœ°å€: %d, å€¼: %lu\n", addr, value);
        }
        else {
            TRACE("\n写入失败: å¾®åŠ¨é‡, åœ°å€: %d, é”™è¯¯ç : %d\n", addr, flag);
        }
    });
    // å†™å…¥å®šä½ç‚¹æ•°æ®
    int positionStartAddress = startAddress + 100;
    for (int i = 0; i < axisData.positions.size(); ++i) {
        const auto& position = axisData.positions[i];
        unsigned int positionAddress = positionStartAddress + (i * 2);
        double valueToWrite = position.range.currentValue;
        m_pPLC->writeDWord(component, positionAddress, (int)(valueToWrite * 1000), [i, positionAddress](IMcChannel* pChannel, int addr, DWORD value, int flag) {
            if (flag == 0) {
                TRACE("\n写入成功: å®šä½ç‚¹ %d, åœ°å€: %d, å€¼: %lu\n", i + 1, positionAddress, value);
            }
            else {
                TRACE("\n写入失败: å®šä½ç‚¹ %d, åœ°å€: %d, é”™è¯¯ç : %d\n", i + 1, positionAddress, flag);
            }
        });
    }
}
void CAxisSettingsDlg::HandleAxisOperation(AxisOperationType eOpType, bool bPressed)
{
    int nAxisId = GetCurrentSelectedAxisID();
    if (nAxisId == -1) {
        AfxMessageBox(_T("未选择有效的轴编号!"));
        return;
    }
    // èŽ·å–è½´æ•°æ®
    auto axisData = m_pAxisManager->GetAxis(nAxisId);
    int startAddress;
    MC::SOFT_COMPONENT component;
    if (!ParsePLCAddress(CString(axisData.startAddress.c_str()), component, startAddress)) {
        AfxMessageBox(_T("无效的起始地址!"));
    }
    // æ ¹æ®æ“ä½œç±»åž‹è®¡ç®—目标地址
    int bitIndex = 0;
    char szWrite[4] = { 0x0, 0x0, 0x0, 0x0 };
    switch (eOpType) {
    case AxisOperationType::OPR:
        startAddress += 0; // OPR ä¿¡å·åœ°å€ 0,闪动信息06.0
        szWrite[0] = bPressed ? 0x1 : 0;
        break;
    case AxisOperationType::JOG_ADD:
        startAddress += 01; // JOG+ ä¿¡å·åœ°å€ c
        szWrite[1] = bPressed ? 0x10 : 0;
        break;
    case AxisOperationType::JOG_SUB:
        startAddress += 01; // JOG- ä¿¡å·åœ°å€ d
        szWrite[1] = bPressed ? 0x20 : 0;
        break;
    case AxisOperationType::STOP:
        startAddress += 05; // STOP ä¿¡å·åœ°å€ 5.e
        szWrite[1] = bPressed ? 0x40 : 0;
        break;
    case AxisOperationType::SEV_ON:
        startAddress += 01; // SEV_ON ä¿¡å·åœ°å€ 1.a
        szWrite[1] = bPressed ? 0x04 : 0;
        break;
    case AxisOperationType::POSITION_1:
    case AxisOperationType::POSITION_2:
    case AxisOperationType::POSITION_3:
    case AxisOperationType::POSITION_4:
    case AxisOperationType::POSITION_5:
        startAddress += ((m_currentPage - 1) * 5 + ((int)eOpType - (int)AxisOperationType::POSITION_1 + 1)) / 16;
        bitIndex = ((m_currentPage-1) * 5 + ((int)eOpType - (int)AxisOperationType::POSITION_1 + 1)) % 16;
        if(bPressed) CToolUnits::setBit(szWrite, bitIndex);
        break;
    default:
        AfxMessageBox(_T("未知操作类型!"));
        return;
    }
    // å‘ PLC å†™å…¥ä¿¡å·
    m_pPLC->writeData(component, startAddress, szWrite, 2, [eOpType, startAddress, bPressed](IMcChannel* pChannel, int nAddr, DWORD nValue, int nFlag) {
        if (nFlag == 0) {
            TRACE("操作成功:类型=%d,地址=%d,值=%d\n", static_cast<int>(eOpType), nAddr, bPressed);
        }
        else {
            TRACE("操作失败:类型=%d,地址=%d,错误码=%d\n", static_cast<int>(eOpType), nAddr, nFlag);
        }
    });
}
void CAxisSettingsDlg::ReadPLCDataToUI(int nAxisId)
{
    AxisInfo axisData = m_pAxisManager->GetAxis(nAxisId);
    MC::SOFT_COMPONENT component;
    int startAddress, endAddress, readSize;
    if (!ParsePLCAddress(CString(axisData.startAddress.c_str()), component, startAddress)) {
        AfxMessageBox(_T("无效的起始地址!"));
    }
    endAddress = startAddress + 300;
    readSize = (endAddress - startAddress + 1) * 2;
    auto funOnReadData = [this, nAxisId, startAddress, readSize](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
        if (nDataSize == readSize && flag == 0 && ::IsWindow(m_hWnd)) {
            m_fCurPos = CToolUnits::toInt32(&pData[20 * 2]) * 0.001;
            m_fManualSpeed = CToolUnits::toInt32(&pData[82 * 2]) * 0.001;
            m_fAutoSpeed = CToolUnits::toInt32(&pData[84 * 2]) * 0.001;
            m_fPrm = CToolUnits::toInt32(&pData[50 * 2]) * 0.1;
            m_nLoad = CToolUnits::toInt16(&pData[54 * 2]);
            m_nErrCode = CToolUnits::toInt16(&pData[26 * 2]);
            m_nAlarmCode = CToolUnits::toInt16(&pData[27 * 2]);
            m_bSEV = CToolUnits::getBit(pData[1 * 2 + 1], 0xa - 8);
            m_bFLS = CToolUnits::getBit(pData[10 * 2], 1);
            m_bDOG = CToolUnits::getBit(pData[10 * 2], 6);
            m_bRLS = CToolUnits::getBit(pData[10 * 2], 0);
            m_bReady = CToolUnits::getBit(pData[10 * 2 + 1], 0xA - 8);
            m_bBusy = CToolUnits::getBit(pData[10 * 2 + 1], 0xB - 8);
            m_bErr = CToolUnits::getBit(pData[10 * 2 + 1], 0xF - 8);
            // è®°å½•按钮刷新状态
            // 6,7,8,9为原点和25个点位状态和完成状态
            // ZR 06.0 å’Œ 08.0
            // å›žåŽŸç‚¹è¿åŠ¨ä¸­ï¼ŒZR06.0在0和1中切换,回原点完成, 08.0为1
            // ä¿®æ”¹ZR06.0闪烁为1,停止闪烁是0
            // å®šä½1
            // ZR 06.1 å’Œ 08.1
            // ...
            int b = 6 * 2;
            m_nBtnsFlashState6 = ((BYTE)pData[b] | (BYTE)pData[b + 1] << 8);
            m_nBtnsFlashState6 |= ((BYTE)pData[b + 2] << 16 | (BYTE)pData[b + 3] << 24);
            m_nBtnsFlashState8 = ((BYTE)pData[b + 4] | (BYTE)pData[b + 5] << 8);
            m_nBtnsFlashState8 |= ((BYTE)pData[b + 6] << 16 | (BYTE)pData[b + 7] << 24);
            // è¯»å–定位点数据
            AxisInfo axisInfo = m_pAxisManager->GetAxis(nAxisId);
            for (int i = 0; i < axisInfo.positions.size(); ++i) {
                if (axisInfo.positions[i].isEnable == FALSE) {
                    unsigned int positionAddress = 100 + (i * 2);
                    axisInfo.positions[i].range.currentValue = CToolUnits::toInt32(&pData[positionAddress * 2]) * 0.001;
                }
            }
            m_pAxisManager->UpdateAxis(axisInfo);
            PostMessage(ID_MSG_UPDATA_DATA_TO_UI);
        }
    };
    m_pPLC->readData(component, startAddress, readSize, funOnReadData);
}
BEGIN_MESSAGE_MAP(CAxisSettingsDlg, CBaseDlg)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_LAST, &CAxisSettingsDlg::OnBnClickedButtonAxisLast)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_NEXT, &CAxisSettingsDlg::OnBnClickedButtonAxisNext)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP1, &CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup1)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP2, &CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup2)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP3, &CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup3)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP4, &CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup4)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP5, &CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup5)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_ANCHOR_POINT1, &CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPoint1)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_ANCHOR_POINT2, &CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPoint2)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_ANCHOR_POINT3, &CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPoint3)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_ANCHOR_POINT4, &CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPoint4)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_ANCHOR_POINT5, &CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPoint5)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_TEST_OPR, &CAxisSettingsDlg::OnBnClickedButtonAxisTestOpr)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_TEST_STOP, &CAxisSettingsDlg::OnBnClickedButtonAxisTestStop)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_SEV, &CAxisSettingsDlg::OnBnClickedButtonAxisSev)
    ON_CBN_SELCHANGE(IDC_COMBO_AXIS_NAME, &CAxisSettingsDlg::OnSelchangeComboAxisName)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_SAVE, &CAxisSettingsDlg::OnBnClickedButtonAxisSave)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_UPDATE_UI, &CAxisSettingsDlg::OnBnClickedButtonAxisUpdateUi)
    ON_BN_CLICKED(IDC_BUTTON_AXIS_DETAIL_SETTINGS, &CAxisSettingsDlg::OnBnClickedButtonAxisDetailSettings)
    ON_MESSAGE(ID_MSG_UPDATA_DATA_TO_UI, &CAxisSettingsDlg::OnUpdateDataToUI)
    ON_WM_SIZE()
    ON_WM_TIMER()
    ON_WM_CLOSE()
END_MESSAGE_MAP()
// CAxisSettingsDlg æ¶ˆæ¯å¤„理程序
BOOL CAxisSettingsDlg::OnInitDialog()
{
    CBaseDlg::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    if (m_pPLC == nullptr || !m_pPLC->isConnected()) {
        AfxMessageBox(_T("PLC æœªè¿žæŽ¥ï¼"));
        return FALSE;
    }
    CString strTitle;
    strTitle.Format(_T("轴设定页面(PLC: %s)"), m_pPLC->getName().c_str());
    SetWindowText(strTitle);
    // éšè—å…‰æ ‡
    HideEditCursor(IDC_EDIT_AXIS_CURR_POS);
    HideEditCursor(IDC_EDIT_AXIS_CURR_MANUAL_SPEED);
    HideEditCursor(IDC_EDIT_AXIS_CURR_AUTO_SPEED);
    HideEditCursor(IDC_EDIT_AXIS_CURR_ROTA_SPEED);
    HideEditCursor(IDC_EDIT_AXIS_CURR_LOAD);
    HideEditCursor(IDC_EDIT_AXIS_CURR_ERROR_NUMBER);
    HideEditCursor(IDC_EDIT_AXIS_CURR_ALARM_NUMBER);
    // è®¾ç½®æµ‹è¯•状态
    m_pBlLabels[LABEL_FLS]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_FLS, this);
    m_pBlLabels[LABEL_DOG]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_DOG, this);
    m_pBlLabels[LABEL_RLS]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_RLS, this);
    m_pBlLabels[LABEL_READY]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_READY, this);
    m_pBlLabels[LABEL_BUSY]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_BUSY, this);
    m_pBlLabels[LABEL_ERR]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_ERR, this);
    for (auto pLabel : m_pBlLabels) {
        pLabel->SetBkColor(RGB(0, 180, 0));
        pLabel->SetRoundedCorners(TRUE, 10);
        pLabel->DisableBorder();
        pLabel->SetTextColor(RGB(0, 0, 0));
        pLabel->SetAlignment(AlignCenter);
        pLabel->SetDynamicFont(TRUE);
        AdjustLabelFont(*pLabel);
    }
    // åˆå§‹åŒ–编辑框
    m_pRegexEdit[EDIT_MANUAL_SPEED]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_MANUAL_SPEED, this);
    m_pRegexEdit[EDIT_AUTO_SPEED]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED, this);
    m_pRegexEdit[EDIT_ACCE_TIME]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME, this);
    m_pRegexEdit[EDIT_DECE_TIME]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME, this);
    m_pRegexEdit[EDIT_MICROMENTUM]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM, this);
    m_pRegexEdit[EDIT_ANCHOR_POINT1]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT1, this);
    m_pRegexEdit[EDIT_ANCHOR_POINT2]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT2, this);
    m_pRegexEdit[EDIT_ANCHOR_POINT3]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT3, this);
    m_pRegexEdit[EDIT_ANCHOR_POINT4]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT4, this);
    m_pRegexEdit[EDIT_ANCHOR_POINT5]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT5, this);
    // æŒ‰é’®åˆå§‹åŒ–
    m_pBlBtns[BTN_PAGE1]->SubclassDlgItem(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP1, this);
    m_pBlBtns[BTN_PAGE2]->SubclassDlgItem(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP2, this);
    m_pBlBtns[BTN_PAGE3]->SubclassDlgItem(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP3, this);
    m_pBlBtns[BTN_PAGE4]->SubclassDlgItem(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP4, this);
    m_pBlBtns[BTN_PAGE5]->SubclassDlgItem(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP5, this);
    m_pBlBtns[BTN_JOG_ADD]->SubclassDlgItem(IDC_BUTTON_AXIS_TEST_JOG_ADD, this);
    m_pBlBtns[BTN_JOG_ADD]->SetFrameColor(BS_NORMAL, BTN_JOG_FRAME_NORMAL);
    m_pBlBtns[BTN_JOG_ADD]->SetFrameColor(BS_HOVER, BTN_JOG_FRAME_HOVER);
    m_pBlBtns[BTN_JOG_ADD]->SetFrameColor(BS_PRESS, BTN_JOG_FRAME_PRESS);
    m_pBlBtns[BTN_JOG_ADD]->SetBkgndColor(BS_NORMAL, BTN_JOG_BKGND_NORMAL);
    m_pBlBtns[BTN_JOG_ADD]->SetBkgndColor(BS_HOVER, BTN_JOG_BKGND_HOVER);
    m_pBlBtns[BTN_JOG_ADD]->SetBkgndColor(BS_PRESS, BTN_JOG_BKGND_PRESS);
    m_pBlBtns[BTN_JOG_SUB]->SubclassDlgItem(IDC_BUTTON_AXIS_TEST_JOG_SUB, this);
    m_pBlBtns[BTN_JOG_SUB]->SetFrameColor(BS_NORMAL, BTN_JOG_FRAME_NORMAL);
    m_pBlBtns[BTN_JOG_SUB]->SetFrameColor(BS_HOVER, BTN_JOG_FRAME_HOVER);
    m_pBlBtns[BTN_JOG_SUB]->SetFrameColor(BS_PRESS, BTN_JOG_FRAME_PRESS);
    m_pBlBtns[BTN_JOG_SUB]->SetBkgndColor(BS_NORMAL, BTN_JOG_BKGND_NORMAL);
    m_pBlBtns[BTN_JOG_SUB]->SetBkgndColor(BS_HOVER, BTN_JOG_BKGND_HOVER);
    m_pBlBtns[BTN_JOG_SUB]->SetBkgndColor(BS_PRESS, BTN_JOG_BKGND_PRESS);
    m_pBlBtns[BTN_JOG_SEV]->SubclassDlgItem(IDC_BUTTON_AXIS_SEV, this);
    m_pBlBtns[BTN_JOG_SEV]->SetFrameColor(BS_NORMAL, BTN_SEV_FRAME_NORMAL);
    m_pBlBtns[BTN_JOG_SEV]->SetFrameColor(BS_HOVER, BTN_SEV_FRAME_HOVER);
    m_pBlBtns[BTN_JOG_SEV]->SetFrameColor(BS_PRESS, BTN_SEV_FRAME_PRESS);
    m_pBlBtns[BTN_JOG_SEV]->SetBkgndColor(BS_NORMAL, BTN_SEV_BKGND_NORMAL);
    m_pBlBtns[BTN_JOG_SEV]->SetBkgndColor(BS_HOVER, BTN_SEV_BKGND_HOVER);
    m_pBlBtns[BTN_JOG_SEV]->SetBkgndColor(BS_PRESS, BTN_SEV_BKGND_PRESS);
    m_pBlBtns[BTN_JOG_STOP]->SubclassDlgItem(IDC_BUTTON_AXIS_TEST_STOP, this);
    m_pBlBtns[BTN_JOG_STOP]->SetFrameColor(BS_NORMAL, BTN_STOP_FRAME_NORMAL);
    m_pBlBtns[BTN_JOG_STOP]->SetFrameColor(BS_HOVER, BTN_STOP_FRAME_HOVER);
    m_pBlBtns[BTN_JOG_STOP]->SetFrameColor(BS_PRESS, BTN_STOP_FRAME_PRESS);
    m_pBlBtns[BTN_JOG_STOP]->SetBkgndColor(BS_NORMAL, BTN_STOP_BKGND_NORMAL);
    m_pBlBtns[BTN_JOG_STOP]->SetBkgndColor(BS_HOVER, BTN_STOP_BKGND_HOVER);
    m_pBlBtns[BTN_JOG_STOP]->SetBkgndColor(BS_PRESS, BTN_STOP_BKGND_PRESS);
    m_pBlBtns[BTN_JOG_OPR]->SubclassDlgItem(IDC_BUTTON_AXIS_TEST_OPR, this);
    m_pBlBtns[BTN_JOG_OPR]->SetFrameColor(BS_NORMAL, BTN_OPR_FRAME_NORMAL);
    m_pBlBtns[BTN_JOG_OPR]->SetFrameColor(BS_HOVER, BTN_OPR_FRAME_HOVER);
    m_pBlBtns[BTN_JOG_OPR]->SetFrameColor(BS_PRESS, BTN_OPR_FRAME_PRESS);
    m_pBlBtns[BTN_JOG_OPR]->SetBkgndColor(BS_NORMAL, BTN_OPR_BKGND_NORMAL);
    m_pBlBtns[BTN_JOG_OPR]->SetBkgndColor(BS_HOVER, BTN_OPR_BKGND_HOVER);
    m_pBlBtns[BTN_JOG_OPR]->SetBkgndColor(BS_PRESS, BTN_OPR_BKGND_PRESS);
    static UINT btnPointIds[] = { IDC_BUTTON_AXIS_ANCHOR_POINT1, IDC_BUTTON_AXIS_ANCHOR_POINT2,
        IDC_BUTTON_AXIS_ANCHOR_POINT3, IDC_BUTTON_AXIS_ANCHOR_POINT4, IDC_BUTTON_AXIS_ANCHOR_POINT5};
    for (int i = 0; i < 5; i++) {
        m_pBlBtns[BTN_POINT1 + i]->SubclassDlgItem(btnPointIds[i], this);
        m_pBlBtns[BTN_POINT1 + i]->SetFrameColor(BS_NORMAL, BTN_POINT_FRAME_NORMAL);
        m_pBlBtns[BTN_POINT1 + i]->SetFrameColor(BS_HOVER, BTN_POINT_FRAME_HOVER);
        m_pBlBtns[BTN_POINT1 + i]->SetFrameColor(BS_PRESS, BTN_POINT_FRAME_PRESS);
        m_pBlBtns[BTN_POINT1 + i]->SetBkgndColor(BS_NORMAL, BTN_POINT_BKGND_NORMAL);
        m_pBlBtns[BTN_POINT1 + i]->SetBkgndColor(BS_HOVER, BTN_POINT_BKGND_HOVER);
        m_pBlBtns[BTN_POINT1 + i]->SetBkgndColor(BS_PRESS, BTN_POINT_BKGND_PRESS);
    }
    // åˆå§‹åŒ–当前页面为第一页
    m_currentPage = 1;
    UpdatePageButtonStates();
    InitializeAxisIDCombo();
    RefreshAxisDetails(1);
    RefreshPositionDetails(1, m_currentPage);
    SetTimer(TIMER_READ_PLC_DATA, 500, nullptr);
    return TRUE;  // return TRUE unless you set the focus to a control
    // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
BOOL CAxisSettingsDlg::PreTranslateMessage(MSG* pMsg)
{
    // TODO: åœ¨æ­¤æ·»åŠ ä¸“ç”¨ä»£ç å’Œ/或调用基类
    CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);
    if (pWnd) {
        if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) {
            // é˜»æ­¢å›žè½¦é”®é»˜è®¤å¤„理,防止对话框关闭
            return TRUE;
        }
        // åˆ¤æ–­é¼ æ ‡æ˜¯å¦è¿›å…¥æŒ‡å®šæŽ§ä»¶åŒºåŸŸ
        if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP1)->m_hWnd ||
            pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP2)->m_hWnd ||
            pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP3)->m_hWnd ||
            pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP4)->m_hWnd ||
            pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP5)->m_hWnd) {
            int currentIndex = -1;
            // æ ¹æ®æŽ§ä»¶ID确定 currentIndex
            if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP1)->m_hWnd) {
                currentIndex = 0;
            }
            else if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP2)->m_hWnd) {
                currentIndex = 1;
            }
            else if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP3)->m_hWnd) {
                currentIndex = 2;
            }
            else if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP4)->m_hWnd) {
                currentIndex = 3;
            }
            else if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP5)->m_hWnd) {
                currentIndex = 4;
            }
            if (currentIndex == -1) {
                return CBaseDlg::PreTranslateMessage(pMsg);
            }
            CString descriptionCtrlName, positionCtrlName;
            descriptionCtrlName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP%d"), currentIndex + 1);
            positionCtrlName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT%d"), currentIndex + 1);
            UINT descriptionCtrlId = FindIDByName(descriptionCtrlName);
            UINT positionCtrlId = FindIDByName(positionCtrlName);
            CWnd* pDescriptionCtrl = GetDlgItem(descriptionCtrlId);
            CWnd* pPositionCtrl = GetDlgItem(positionCtrlId);
            if (pDescriptionCtrl == nullptr || pPositionCtrl == nullptr) {
                return CBaseDlg::PreTranslateMessage(pMsg);
            }
            PositionRange& position = m_pAxisManager->GetPositionByIndex(GetCurrentSelectedAxisID(), m_currentPage, AXIS_PAGE_SIZE, currentIndex);
            if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK) {
                // å¤„理鼠标点击事件
                // è®¾ç½®é¼ æ ‡ä¸ºç®­å¤´å…‰æ ‡
                ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
                CString strText;
                GetDlgItem(IDC_EDIT_AXIS_CURR_POS)->GetWindowText(strText);
                if (strText.IsEmpty()) {
                    return CBaseDlg::PreTranslateMessage(pMsg);;
                }
                double enteredValue = _ttof(strText);
                double minValue = position.range.minValue;
                double maxValue = position.range.maxValue;
                // åˆ¤æ–­è¾“入的值是否在合法范围内
                if (enteredValue < minValue || enteredValue > maxValue) {
                    CString strError;
                    strError.Format(_T("定位点的值必须在 %f å’Œ %f ä¹‹é—´ï¼"), minValue, maxValue);
                    pDescriptionCtrl->SetWindowText(strError);
                }
                else {
                    position.range.currentValue = enteredValue;
                    pPositionCtrl->SetWindowText(strText);
                }
            }
            else if (pMsg->message == WM_LBUTTONUP) {
                // å¤„理鼠标抬起事件
                // è®¾ç½®é¼ æ ‡ä¸ºæ‰‹å½¢å…‰æ ‡
                ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_HAND));
                CString strText;
                strText.Format(_T("%s"), position.description.c_str());
                pDescriptionCtrl->SetWindowText(strText);
            }
            else if (pMsg->message == WM_MOUSEMOVE) {
                // å¤„理鼠标移动事件
                ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_HAND));
            }
        }
        if (pMsg->message == WM_LBUTTONDOWN) {
            if (pMsg->hwnd == GetDlgItem(IDC_BUTTON_AXIS_TEST_JOG_ADD)->m_hWnd) {
                TRACE("JOG+ æŒ‰é’®æŒ‰ä¸‹\n");
                HandleAxisOperation(AxisOperationType::JOG_ADD, true);
            }
            else if (pMsg->hwnd == GetDlgItem(IDC_BUTTON_AXIS_TEST_JOG_SUB)->m_hWnd) {
                TRACE("JOG- æŒ‰é’®æŒ‰ä¸‹\n");
                // å¯åŠ¨å®šæ—¶å™¨è¿žç»­å‘é€ä¿¡å·
                HandleAxisOperation(AxisOperationType::JOG_SUB, true);
            }
        }
        else if (pMsg->message == WM_LBUTTONUP) {
            if (pMsg->hwnd == GetDlgItem(IDC_BUTTON_AXIS_TEST_JOG_ADD)->m_hWnd) {
                TRACE("JOG+ æŒ‰é’®æ¾å¼€\n");
                HandleAxisOperation(AxisOperationType::JOG_ADD, false);
            }
            else if (pMsg->hwnd == GetDlgItem(IDC_BUTTON_AXIS_TEST_JOG_SUB)->m_hWnd) {
                TRACE("JOG- æŒ‰é’®æ¾å¼€\n");
                HandleAxisOperation(AxisOperationType::JOG_SUB, false);
            }
        }
    }
    return CBaseDlg::PreTranslateMessage(pMsg);
}
void CAxisSettingsDlg::OnSize(UINT nType, int cx, int cy)
{
    CBaseDlg::OnSize(nType, cx, cy);
    // TODO: åœ¨æ­¤å¤„添加消息处理程序代码
    // åŠ¨æ€è°ƒæ•´å„ä¸ª CBLLabel çš„字体大小
    for (auto pLabel : m_pBlLabels) {
        AdjustLabelFont(*pLabel);
    }
    // è°ƒæ•´ä¸‹æ‹‰æ¡†é«˜åº¦
    CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_AXIS_NAME);
    CButton* pButtonLeft = (CButton*)GetDlgItem(IDC_BUTTON_AXIS_LAST);
    CButton* pButtonRight = (CButton*)GetDlgItem(IDC_BUTTON_AXIS_NEXT);
    if (pComboBox && pButtonLeft && pButtonRight) {
        CRect rectButton;
        pButtonLeft->GetWindowRect(&rectButton);    // èŽ·å–æŒ‰é’®å°ºå¯¸
        ScreenToClient(&rectButton);                // è½¬æ¢ä¸ºå®¢æˆ·ç«¯åæ ‡
        CRect rectComboBox;
        pComboBox->GetWindowRect(&rectComboBox);
        ScreenToClient(&rectComboBox);
        // è°ƒæ•´ä¸‹æ‹‰æ¡†é«˜åº¦
        int heightAdjustment = 2;
        rectComboBox.top = rectButton.top;
        rectComboBox.bottom = rectButton.bottom + heightAdjustment;
        pComboBox->MoveWindow(&rectComboBox);
        pComboBox->SetItemHeight(-1, rectButton.Height() - 6);
    }
}
void CAxisSettingsDlg::OnBnClickedButtonAxisLast()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    UpdateAxisSelection(-1);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisNext()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    UpdateAxisSelection(1);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup1()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    SwitchToPage(1);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup2()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    SwitchToPage(2);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup3()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    SwitchToPage(3);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup4()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    SwitchToPage(4);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup5()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    SwitchToPage(5);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPoint1()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleAxisOperation(AxisOperationType::POSITION_1, true);
    Sleep(200);
    HandleAxisOperation(AxisOperationType::POSITION_1, false);
    m_pBlBtns[BTN_POINT1]->Flash(500);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPoint2()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleAxisOperation(AxisOperationType::POSITION_2, true);
    Sleep(200);
    HandleAxisOperation(AxisOperationType::POSITION_2, false);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPoint3()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleAxisOperation(AxisOperationType::POSITION_3, true);
    Sleep(200);
    HandleAxisOperation(AxisOperationType::POSITION_3, false);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPoint4()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleAxisOperation(AxisOperationType::POSITION_4, true);
    Sleep(200);
    HandleAxisOperation(AxisOperationType::POSITION_4, false);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPoint5()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleAxisOperation(AxisOperationType::POSITION_5, true);
    Sleep(200);
    HandleAxisOperation(AxisOperationType::POSITION_5, false);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisTestOpr()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleAxisOperation(AxisOperationType::OPR, true);
    Sleep(200);
    HandleAxisOperation(AxisOperationType::OPR, false);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisTestStop()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleAxisOperation(AxisOperationType::STOP, true);
    Sleep(200);
    HandleAxisOperation(AxisOperationType::STOP, false);
    m_pBlBtns[BTN_JOG_OPR]->StopFlash();
    m_pBlBtns[BTN_POINT1]->StopFlash();
    m_pBlBtns[BTN_POINT2]->StopFlash();
    m_pBlBtns[BTN_POINT3]->StopFlash();
    m_pBlBtns[BTN_POINT3]->StopFlash();
    m_pBlBtns[BTN_POINT4]->StopFlash();
}
void CAxisSettingsDlg::OnBnClickedButtonAxisSev()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleAxisOperation(AxisOperationType::SEV_ON, !m_bSEV);
}
void CAxisSettingsDlg::OnSelchangeComboAxisName()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    int axisId = GetCurrentSelectedAxisID();
    if (axisId == -1) {
        AfxMessageBox(_T("请选择一个有效的轴编号!"));
        return;
    }
    RefreshAxisDetails(axisId);
    RefreshPositionDetails(axisId, m_currentPage);
    UpdatePageButtonStates();
}
void CAxisSettingsDlg::OnBnClickedButtonAxisSave()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    int axisId = GetCurrentSelectedAxisID();
    if (axisId == -1) {
        AfxMessageBox(_T("请选择一个有效的轴编号!"));
        return;
    }
    CString cstrMessage;
    cstrMessage.Format(_T("是否保存轴 [%d] å‚数?"), axisId);
    int ret = AfxMessageBox(_T(cstrMessage), MB_OKCANCEL | MB_ICONEXCLAMATION);
    if (ret != IDOK) {
        return;
    }
    UpdateDataFromUI(axisId);
    if (m_pAxisManager->SaveAxis(m_pPLC->getName())) {
        WriteAxisDataToPLC(axisId);
        cstrMessage.Format(_T("保存轴 [%d] å‚数成功!"), axisId);
    }
    else {
        cstrMessage.Format(_T("保存轴 [%d] å‚数失败!"), axisId);
    }
    AfxMessageBox(cstrMessage);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisUpdateUi()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    int axisId = GetCurrentSelectedAxisID();
    if (axisId == -1) {
        AfxMessageBox(_T("请选择一个有效的轴编号!"));
        return;
    }
    RefreshAxisDetails(axisId);
    RefreshPositionDetails(axisId, m_currentPage);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisDetailSettings()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    int nAxisId = GetCurrentSelectedAxisID();
    if (nAxisId == -1) {
        AfxMessageBox(_T("请选择一个有效的轴编号!"));
        return;
    }
    CAxisDetailSettingsDlg dlg(m_pAxisManager, nAxisId, this);
    dlg.DoModal();
    RefreshAxisDetails(nAxisId);
    RefreshPositionDetails(nAxisId, m_currentPage);
}
LRESULT CAxisSettingsDlg::OnUpdateDataToUI(WPARAM wParam, LPARAM lParam)
{
    CToolUnits::setDlgItemDouble(this, IDC_EDIT_AXIS_CURR_POS, m_fCurPos);
    CToolUnits::setDlgItemDouble(this, IDC_EDIT_AXIS_CURR_MANUAL_SPEED, m_fManualSpeed);
    CToolUnits::setDlgItemDouble(this, IDC_EDIT_AXIS_CURR_AUTO_SPEED, m_fAutoSpeed);
    CToolUnits::setDlgItemDouble(this, IDC_EDIT_AXIS_CURR_ROTA_SPEED, m_fPrm);
    SetDlgItemInt(IDC_EDIT_AXIS_CURR_LOAD, m_nLoad);
    SetDlgItemInt(IDC_EDIT_AXIS_CURR_ERROR_NUMBER, m_nErrCode);
    SetDlgItemInt(IDC_EDIT_AXIS_CURR_ALARM_NUMBER, m_nAlarmCode);
    // æ›´æ–°Labels状态
    UpdateLabels();
    // æ›´æ–°ä¸å¯å†™çš„定位点数据
    for (int i = 0; i < AXIS_PAGE_SIZE; ++i) {
        PositionRange position = m_pAxisManager->GetPositionByIndex(GetCurrentSelectedAxisID(), m_currentPage, AXIS_PAGE_SIZE, 0);
        if (position.isEnable) {
            continue;
        }
        CString positionName;
        positionName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT%d"), i + 1);
        CEdit* pPositionEdit = (CEdit*)GetDlgItem(FindIDByName(positionName));
        if (pPositionEdit) {
            CString positionValue;
            positionValue.Format(_T("%.3f"), position.range.currentValue);
            pPositionEdit->GetWindowText(positionValue);
        }
    }
    // ZR 06.0 å’Œ 08.0
    // å›žåŽŸç‚¹è¿åŠ¨ä¸­ï¼ŒZR06.0在0和1中切换,回原点完成, 08.0为1
    // ä¿®æ”¹ZR06.0闪烁为1,停止闪烁是0
    // OPR按钮是否要闪烁或停止闪烁
    // 06.0和08.0
    if (m_nBtnsFlashState6 & 0x01) {
        // 06.0
        if (!m_pBlBtns[BTN_JOG_OPR]->IsFlash()) {
            m_pBlBtns[BTN_JOG_OPR]->Flash(500);
        }
    }
    else {
        if (m_pBlBtns[BTN_JOG_OPR]->IsFlash()) {
            m_pBlBtns[BTN_JOG_OPR]->StopFlash();
        }
    }
    if (m_nBtnsFlashState8 & 0x01) {
        // å®Œæˆä¿¡å·
        if (m_pBlBtns[BTN_JOG_OPR]->IsFlash()) {
            m_pBlBtns[BTN_JOG_OPR]->StopFlash();
        }
        m_pBlBtns[BTN_JOG_OPR]->SetBkgndColor(BS_NORMAL, BTN_OPR_BKGND_TEST);
        m_pBlBtns[BTN_JOG_OPR]->Invalidate();
    }
    else {
        m_pBlBtns[BTN_JOG_OPR]->SetBkgndColor(BS_NORMAL, BTN_OPR_BKGND_NORMAL);
        m_pBlBtns[BTN_JOG_OPR]->Invalidate();
    }
    int v = 0x02;
    if (m_currentPage > 1) {
        v = v << (5 * (m_currentPage - 1));
    }
    if (m_nBtnsFlashState6 & v) {
        if (!m_pBlBtns[BTN_POINT1]->IsFlash()) {
            m_pBlBtns[BTN_POINT1]->Flash(500);
        }
    }
    else if (m_nBtnsFlashState8 & v) {
        if (m_pBlBtns[BTN_POINT1]->IsFlash()) {
            m_pBlBtns[BTN_POINT1]->StopFlash();
        }
    }
    // è®¾ç½®ä½¿èƒ½æŒ‰é’®çŠ¶æ€
    if (m_bSEV) {
        m_pBlBtns[BTN_JOG_SEV]->SetWindowText(_T("Sev-OFF"));
        m_pBlBtns[BTN_JOG_SEV]->SetBkgndColor(BS_NORMAL, BTN_SEV_BKGND_PRESS);
    }
    else {
        m_pBlBtns[BTN_JOG_SEV]->SetWindowText(_T("Sev-ON"));
        m_pBlBtns[BTN_JOG_SEV]->SetBkgndColor(BS_NORMAL, BTN_SEV_BKGND_NORMAL);
    }
    if (m_nBtnsFlashState6 & (v << 1)) {
        if (!m_pBlBtns[BTN_POINT2]->IsFlash()) {
            m_pBlBtns[BTN_POINT2]->Flash(500);
        }
    }
    else if (m_nBtnsFlashState8 & (v << 1)) {
        if (m_pBlBtns[BTN_POINT2]->IsFlash()) {
            m_pBlBtns[BTN_POINT2]->StopFlash();
        }
    }
    if (m_nBtnsFlashState6 & (v << 2)) {
        if (!m_pBlBtns[BTN_POINT3]->IsFlash()) {
            m_pBlBtns[BTN_POINT3]->Flash(500);
        }
    }
    else if (m_nBtnsFlashState8 & (v << 2)) {
        if (m_pBlBtns[BTN_POINT3]->IsFlash()) {
            m_pBlBtns[BTN_POINT3]->StopFlash();
        }
    }
    if (m_nBtnsFlashState6 & (v << 3)) {
        if (!m_pBlBtns[BTN_POINT4]->IsFlash()) {
            m_pBlBtns[BTN_POINT4]->Flash(500);
        }
    }
    else if (m_nBtnsFlashState8 & (v << 3)) {
        if (m_pBlBtns[BTN_POINT4]->IsFlash()) {
            m_pBlBtns[BTN_POINT4]->StopFlash();
        }
    }
    if (m_nBtnsFlashState6 & (v << 4)) {
        if (!m_pBlBtns[BTN_POINT5]->IsFlash()) {
            m_pBlBtns[BTN_POINT5]->Flash(500);
        }
    }
    else if (m_nBtnsFlashState8 & (v << 4)) {
        if (m_pBlBtns[BTN_POINT5]->IsFlash()) {
            m_pBlBtns[BTN_POINT5]->StopFlash();
        }
    }
    return 0;
}
void CAxisSettingsDlg::OnTimer(UINT_PTR nIDEvent)
{
    if (TIMER_READ_PLC_DATA == nIDEvent) {
        ASSERT(m_pPLC);
        int nAxisId = GetCurrentSelectedAxisID();
        if (nAxisId == -1) {
            return;
        }
        ReadPLCDataToUI(nAxisId);
    }
    CBaseDlg::OnTimer(nIDEvent);
}
void CAxisSettingsDlg::OnClose()
{
    // TODO: åœ¨æ­¤æ·»åŠ æ¶ˆæ¯å¤„ç†ç¨‹åºä»£ç å’Œ/或调用默认值
    KillTimer(TIMER_READ_PLC_DATA);
    CBaseDlg::OnClose();
}
SourceCode/Bond/BoounionPLC/AxisSettingsDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,164 @@
#pragma once
#include "BlButton.h"
#include "BLLabel.h"
#include "RegexEdit.h"
#include "CBaseDlg.h"
#include "PLC.h"
#include "AxisManager.h"
// æ¯é¡µå®šä½ç‚¹æ˜¾ç¤ºä¸ªæ•°
#define AXIS_PAGE_SIZE    5
// Label控件
#define LABEL_MAX        6
#define LABEL_FLS        0
#define LABEL_DOG        1
#define LABEL_RLS        2
#define LABEL_READY        3
#define LABEL_BUSY        4
#define LABEL_ERR        5
// RegexEdit控件
#define EDIT_MAX            10
#define EDIT_MANUAL_SPEED    0
#define EDIT_AUTO_SPEED        1
#define EDIT_ACCE_TIME        2
#define EDIT_DECE_TIME        3
#define EDIT_MICROMENTUM    4
#define EDIT_ANCHOR_POINT1    5
#define EDIT_ANCHOR_POINT2    6
#define EDIT_ANCHOR_POINT3    7
#define EDIT_ANCHOR_POINT4    8
#define EDIT_ANCHOR_POINT5    9
// BUTTON控件
#define BTN_MAX            15
#define BTN_PAGE1        0
#define BTN_PAGE2        1
#define BTN_PAGE3        2
#define BTN_PAGE4        3
#define BTN_PAGE5        4
#define BTN_JOG_ADD        5
#define BTN_JOG_SUB        6
#define BTN_JOG_SEV        7
#define BTN_JOG_OPR        8
#define BTN_JOG_STOP    9
#define BTN_POINT1        10
#define BTN_POINT2        11
#define BTN_POINT3        12
#define BTN_POINT4        13
#define BTN_POINT5        14
// CAxisSettingsDlg å¯¹è¯æ¡†
enum class AxisOperationType {
    OPR = 0,    // å›žåŽŸç‚¹
    JOG_ADD,    // æ­£å‘点动
    JOG_SUB,    // åå‘点动
    STOP,        // åœæ­¢æ“ä½œ
    SEV_ON,        // ä½¿èƒ½
    POSITION_1, // å®šä½ç‚¹1
    POSITION_2, // å®šä½ç‚¹2
    POSITION_3, // å®šä½ç‚¹3
    POSITION_4, // å®šä½ç‚¹4
    POSITION_5  // å®šä½ç‚¹5
};
class CAxisSettingsDlg : public CBaseDlg
{
    DECLARE_DYNAMIC(CAxisSettingsDlg)
public:
    CAxisSettingsDlg(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CAxisSettingsDlg();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_AXIS_SETTINGS };
#endif
private:
    UINT FindIDByName(const CString& strControlID);
    void AdjustLabelFont(CBLLabel& label);
    void SetLabelColor(CBLLabel& label, COLORREF color);
    void SetLabelColorBasedOnState(CBLLabel& label, BOOL bState, COLORREF colorTrue, COLORREF colorFalse);
    void UpdateLabels();
    void UpdateRegexEdit(CRegexEdit* pRegexEdit, const ValueRange& range, const CString& title);
    void UpdatePageButtonStates();
    void HideEditCursor(int nCtrlID);
    int GetCurrentSelectedAxisID();
    void InitializeAxisIDCombo();
    void RefreshAxisDetails(int nAxisId);
    void RefreshPositionDetails(int nAxisId, int pageNumber);
    void UpdatePositionRange(PositionRange& position, int pageNumber, int pageSize, int currentIndex);
    void UpdateAxisSelection(int offset);
    void UpdateDataFromUI(int nAxisId);
    void SwitchToPage(int targetPage);
    bool ParsePLCAddress(const CString& address, MC::SOFT_COMPONENT& component, int& addr);
    void WriteAxisDataToPLC(int nAxisId);
    void HandleAxisOperation(AxisOperationType eOpType, bool bPressed);
    void ReadPLCDataToUI(int nAxisId);
private:
    CPLC* m_pPLC;
    // å½“前选中的定位页面索引
    int m_currentPage;
    // è½´ç®¡ç†å™¨
    AxisManager* m_pAxisManager;
    // æŽ§ä»¶
    CBlButton* m_pBlBtns[BTN_MAX];
    CBLLabel* m_pBlLabels[LABEL_MAX];
    CRegexEdit* m_pRegexEdit[EDIT_MAX];
    CComboBox m_comboAxisNO;
    CStatic m_staticAxisNO, m_staticAxisDescription, m_staticStartAddress;
    // è¯»åˆ°çš„æ•°æ®
    BOOL m_bSEV;
    double m_fCurPos;
    double m_fManualSpeed;
    double m_fAutoSpeed;
    double m_fPrm;
    int m_nLoad;
    int m_nErrCode;
    int m_nAlarmCode;
    BOOL m_bFLS;
    BOOL m_bDOG;
    BOOL m_bRLS;
    BOOL m_bReady;
    BOOL m_bBusy;
    BOOL m_bErr;
    DWORD m_nBtnsFlashState6;
    DWORD m_nBtnsFlashState8;
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    virtual BOOL OnInitDialog();
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnBnClickedButtonAxisLast();
    afx_msg void OnBnClickedButtonAxisNext();
    afx_msg void OnBnClickedButtonAxisAnchorPointGroup1();
    afx_msg void OnBnClickedButtonAxisAnchorPointGroup2();
    afx_msg void OnBnClickedButtonAxisAnchorPointGroup3();
    afx_msg void OnBnClickedButtonAxisAnchorPointGroup4();
    afx_msg void OnBnClickedButtonAxisAnchorPointGroup5();
    afx_msg void OnBnClickedButtonAxisAnchorPoint1();
    afx_msg void OnBnClickedButtonAxisAnchorPoint2();
    afx_msg void OnBnClickedButtonAxisAnchorPoint3();
    afx_msg void OnBnClickedButtonAxisAnchorPoint4();
    afx_msg void OnBnClickedButtonAxisAnchorPoint5();
    afx_msg void OnBnClickedButtonAxisTestOpr();
    afx_msg void OnBnClickedButtonAxisTestStop();
    afx_msg void OnBnClickedButtonAxisSev();
    afx_msg void OnSelchangeComboAxisName();
    afx_msg void OnBnClickedButtonAxisSave();
    afx_msg void OnBnClickedButtonAxisUpdateUi();
    afx_msg void OnBnClickedButtonAxisDetailSettings();
    afx_msg LRESULT OnUpdateDataToUI(WPARAM wParam, LPARAM lParam);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnClose();
    DECLARE_MESSAGE_MAP()
};
SourceCode/Bond/BoounionPLC/BoounionPLC.rc
Binary files differ
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.cpp
@@ -138,14 +138,20 @@
                }
            }
            else if (code == RX_CODE_ALARM_ON) {
                AlarmOn();
                // CAlarmMonitor* pComponent = (CAlarmMonitor*)theApp.m_model.getBonder().GetComponent(ALARM_MONITOR);
                // m_pTopToolbar->GetBtn(IDC_BUTTON_ALARM)->EnableWindow(pComponent->isAlarming());
                CPLC* pPlc;
                if (pAny->getPtrValue("ptr", (void*&)pPlc) && pPlc == theApp.m_model.getCurrentPlc()) {
                    AlarmOn(pPlc);
                    CAlarmMonitor* pComponent = (CAlarmMonitor*)pPlc->getComponent(ALARM_MONITOR);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_ALARM)->EnableWindow(pComponent->isAlarming());
                }
            }
            else if (code == RX_CODE_ALARM_OFF) {
                AlarmOff();
                // CAlarmMonitor* pComponent = (CAlarmMonitor*)theApp.m_model.getBonder().GetComponent(ALARM_MONITOR);
                // m_pTopToolbar->GetBtn(IDC_BUTTON_ALARM)->EnableWindow(pComponent->isAlarming());
                CPLC* pPlc;
                if (pAny->getPtrValue("ptr", (void*&)pPlc) && pPlc == theApp.m_model.getCurrentPlc()) {
                    AlarmOff(pPlc);
                    CAlarmMonitor* pComponent = (CAlarmMonitor*)pPlc->getComponent(ALARM_MONITOR);
                    m_pTopToolbar->GetBtn(IDC_BUTTON_ALARM)->EnableWindow(pComponent->isAlarming());
                }
            }
            pAny->release();
        }, [&]() -> void {
@@ -645,22 +651,22 @@
    m_pMainContainer->Resize();
}
void CBoounionPLCDlg::AlarmOn()
void CBoounionPLCDlg::AlarmOn(CPLC* pPlc)
{
    if (m_pAlarmWnd == nullptr) {
        m_pAlarmWnd = new CAlarmPopupDlg();
        //m_pAlarmWnd->SetPLC(theApp.m_model.getBonder().getPLC("PLC(1)"));
        m_pAlarmWnd->SetPLC(pPlc);
        m_pAlarmWnd->Create(IDD_DIALOG_POPUP_ALARM, this);
        m_pAlarmWnd->CenterWindow();
    }
    m_pAlarmWnd->AlarmOn();
}
void CBoounionPLCDlg::AlarmOff()
void CBoounionPLCDlg::AlarmOff(CPLC* pPlc)
{
    if (m_pAlarmWnd == nullptr) {
        m_pAlarmWnd = new CAlarmPopupDlg();
        //m_pAlarmWnd->SetPLC(theApp.m_model.getBonder().getPLC("PLC(1)"));
        m_pAlarmWnd->SetPLC(pPlc);
        m_pAlarmWnd->Create(IDD_DIALOG_POPUP_ALARM, this);
        m_pAlarmWnd->CenterWindow();
    }
SourceCode/Bond/BoounionPLC/BoounionPLCDlg.h
@@ -23,8 +23,8 @@
    void Resize();
    CBaseView* CreatePlcView(CPLC* pPlc);
    void CloseView(CBaseView* pView);
    void AlarmOn();
    void AlarmOff();
    void AlarmOn(CPLC* pPlc);
    void AlarmOff(CPLC* pPlc);
private:
    COLORREF m_crBkgnd;
SourceCode/Bond/BoounionPLC/CBaseDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,348 @@
#include "stdafx.h"
#include "CBaseDlg.h"
#include "GridCtrl.h"
// å…¨å±€ä¸»é¢˜å¯¹è±¡
Theme g_lightTheme = { RGB(255, 255, 255), RGB(0, 0, 0), RGB(240, 240, 240), RGB(200, 200, 200) };
Theme g_darkTheme = { RGB(40, 40, 40), RGB(255, 255, 255), RGB(60, 60, 60), RGB(80, 80, 80) };
CFont g_defaultFont;
Theme* g_currentTheme = &g_lightTheme;
// å…¨å±€èµ„源句柄
HINSTANCE g_hCurrentResource = NULL;
IMPLEMENT_DYNAMIC(CBaseDlg, CDialogEx)
CBaseDlg::CBaseDlg(UINT nID, CWnd* pPage) : CDialogEx(nID, pPage), m_bResizing(false)
{
    m_nID = nID;
    m_pParent = pPage;
    m_nInitialWidth = 0;
    m_nInitialHeight = 0;
    m_hBrush = CreateSolidBrush(g_currentTheme->backgroundColor);
}
CBaseDlg::~CBaseDlg()
{
    // shared_ptr会自动清理内存,不需要手动删除
    m_mapFonts.clear();
    m_mapCtrlLayouts.clear();
    m_mapControls.clear();
    DeleteObject(m_hBrush);
}
void CBaseDlg::SwitchTheme(ThemeType enThemeType)
{
    // ä½¿ç”¨ map æ¥æ ¹æ® themeType æŸ¥æ‰¾ä¸»é¢˜
    static const std::unordered_map<ThemeType, Theme*> themeMap = {
        { ThemeType::Light, &g_lightTheme },
        { ThemeType::Dark, &g_darkTheme }
    };
    // è®¾ç½®å½“前主题
    auto it = themeMap.find(enThemeType);
    if (it != themeMap.end()) {
        g_currentTheme = it->second;
    }
    else {
        g_currentTheme = &g_lightTheme;
    }
    DeleteObject(m_hBrush);
    m_hBrush = CreateSolidBrush(g_currentTheme->backgroundColor);
    // æ›´æ–°æŽ§ä»¶çš„外观
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        pWnd->Invalidate();
        pWnd = pWnd->GetNextWindow();
    }
    // æ›´æ–°å¯¹è¯æ¡†èƒŒæ™¯é¢œè‰²
    SetBackgroundColor(g_currentTheme->backgroundColor);
}
void CBaseDlg::LoadResourceLibrary(const CString& strLanguage)
{
    // å¸è½½ä¹‹å‰åŠ è½½çš„èµ„æºåº“
    UnloadResourceLibrary();
    // åŠ è½½æ–°çš„èµ„æºåº“
    g_hCurrentResource = AfxLoadLibrary(strLanguage);
    // è®¾ç½®æ–°çš„资源句柄
    if (g_hCurrentResource != NULL) {
        AfxSetResourceHandle(g_hCurrentResource);
    }
}
void CBaseDlg::UnloadResourceLibrary()
{
    // å¸è½½ä¹‹å‰åŠ è½½çš„èµ„æºåº“
    if (g_hCurrentResource != NULL) {
        FreeLibrary(g_hCurrentResource);    // é‡Šæ”¾å½“前资源库
        g_hCurrentResource = NULL;            // æ¸…空资源句柄
    }
}
CFont* CBaseDlg::GetOrCreateFont(int nFontSize)
{
    auto it = m_mapFonts.find(nFontSize);
    if (it != m_mapFonts.end()) {
        return it->second.get();
    }
    // ä½¿ç”¨ shared_ptr æ¥ç®¡ç†å­—体对象
    auto font = std::make_shared<CFont>();
    LOGFONT logFont = { 0 };
    _tcscpy_s(logFont.lfFaceName, _T("Segoe UI"));
    logFont.lfHeight = -nFontSize;
    logFont.lfQuality = CLEARTYPE_QUALITY;
    font->CreateFontIndirect(&logFont);
    m_mapFonts[nFontSize] = font;
    return font.get();
}
void CBaseDlg::SetDefaultFont()
{
    CFont* defaultFont = GetOrCreateFont(12);
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        TCHAR szClassName[256];
        GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
        if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
            pWnd = pWnd->GetNextWindow();
            continue;
        }
        pWnd->SetFont(defaultFont, TRUE);
        pWnd = pWnd->GetNextWindow();
    }
}
BOOL CBaseDlg::AddControl(UINT nCtrlID, CWnd* pControl)
{
    // ç¡®ä¿æŽ§ä»¶ä¸é‡å¤æ·»åŠ 
    if (m_mapControls.find(nCtrlID) != m_mapControls.end()) {
        return FALSE;  // æŽ§ä»¶å·²ç»å­˜åœ¨
    }
    m_mapControls[nCtrlID] = std::unique_ptr<CWnd>(pControl);
    return TRUE;
}
BOOL CBaseDlg::RemoveControl(UINT nCtrlID)
{
    auto it = m_mapControls.find(nCtrlID);
    if (it != m_mapControls.end()) {
        m_mapControls.erase(it);
        return TRUE;
    }
    return FALSE;
}
BOOL CBaseDlg::UpdateControlText(UINT nCtrlID, const CString& strText)
{
    auto it = m_mapControls.find(nCtrlID);
    if (it != m_mapControls.end()) {
        CWnd* pWnd = it->second.get();
        if (pWnd->GetSafeHwnd() != nullptr)
        {
            pWnd->SetWindowText(strText);
            return TRUE;
        }
    }
    return FALSE;
}
CWnd* CBaseDlg::GetControl(UINT nCtrlID)
{
    auto it = m_mapControls.find(nCtrlID);
    if (it != m_mapControls.end()) {
        return it->second.get();
    }
    return nullptr;
}
void CBaseDlg::AdjustControls(float dScaleX, float dScaleY)
{
    if (m_bResizing) return; // é˜²æ­¢åœ¨è°ƒæ•´è¿‡ç¨‹ä¸­é‡å¤è°ƒæ•´
    m_bResizing = true;
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        int nCtrlID = pWnd->GetDlgCtrlID();
        if (nCtrlID != -1 && m_mapCtrlLayouts.find(nCtrlID) != m_mapCtrlLayouts.end()) {
            CRect originalRect = m_mapCtrlLayouts[nCtrlID];
            CRect newRect(
                static_cast<int>(originalRect.left * dScaleX),
                static_cast<int>(originalRect.top * dScaleY),
                static_cast<int>(originalRect.right * dScaleX),
                static_cast<int>(originalRect.bottom * dScaleY));
            TCHAR szClassName[256];
            GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
            if (_tcsicmp(szClassName, _T("ComboBox")) == 0) {
                CComboBox* pComboBox = (CComboBox*)pWnd;
                pComboBox->SetItemHeight(-1, newRect.Height());  // -1 è¡¨ç¤ºæ‰€æœ‰é¡¹çš„高度
            }
            if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
                CGridCtrl* pGridCtrl = (CGridCtrl*)pWnd;
                pGridCtrl->SetDefCellHeight(newRect.Height() / 21);
                pGridCtrl->ExpandColumnsToFit(TRUE);
                pGridCtrl->ExpandLastColumn();
                pGridCtrl->Invalidate();
                pGridCtrl->UpdateWindow();
            }
            pWnd->MoveWindow(&newRect);
            AdjustControlFont(pWnd, newRect.Width(), newRect.Height());
        }
        pWnd = pWnd->GetNextWindow();
    }
    m_bResizing = false;
}
void CBaseDlg::AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight)
{
    TCHAR szClassName[256];
    GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
    if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
        return;
    }
    int fontSize = nHeight / 2;
    if (fontSize < 8) fontSize = 8;
    if (fontSize > 32) fontSize = 32;
    CFont* pFont = GetOrCreateFont(fontSize);
    pWnd->SetFont(pFont);
    pWnd->Invalidate(); // åˆ·æ–°æŽ§ä»¶æ˜¾ç¤º
}
BEGIN_MESSAGE_MAP(CBaseDlg, CDialogEx)
    ON_WM_SIZE()
    ON_WM_GETMINMAXINFO()
    ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
BOOL CBaseDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // èŽ·å–å½“å‰è¯­è¨€
    LANGID langId = GetUserDefaultLangID();
    if (langId == LANG_CHINESE) {
        // åŠ è½½ä¸­æ–‡èµ„æº
    }
    else {
        // åŠ è½½è‹±æ–‡èµ„æº
    }
    // èŽ·å–å¯¹è¯æ¡†çš„å·¥ä½œåŒºï¼ˆå±å¹•å¯ç”¨åŒºåŸŸï¼‰
    CRect screenRect, dlgRect, clientRect;
    SystemParametersInfo(SPI_GETWORKAREA, 0, &screenRect, 0);
    GetClientRect(&clientRect);
    m_nInitialWidth = clientRect.Width();
    m_nInitialHeight = clientRect.Height();
    // è®¾ç½®é»˜è®¤å­—体
    CFont* pDefaultFont = GetOrCreateFont(12);
    // éåŽ†å­çª—å£ï¼ˆæŽ§ä»¶ï¼‰
    CWnd* pWnd = GetWindow(GW_CHILD);
    while (pWnd) {
        int nCtrlID = pWnd->GetDlgCtrlID();
        if (nCtrlID != -1) {
            // ä¿å­˜æŽ§ä»¶çš„初始布局
            CRect ctrlRect;
            pWnd->GetWindowRect(&ctrlRect);
            ScreenToClient(&ctrlRect);
            m_mapCtrlLayouts[nCtrlID] = ctrlRect;
            // æŽ’除不需要操作的控件(如自定义控件 GridCtrl)
            TCHAR szClassName[256];
            GetClassName(pWnd->m_hWnd, szClassName, sizeof(szClassName));
            if (_tcsicmp(szClassName, _T("MFCGridCtrl")) == 0) {
                pWnd = pWnd->GetNextWindow();
                continue;
            }
            // è®¾ç½®æŽ§ä»¶çš„默认字体
            pWnd->SetFont(pDefaultFont);
        }
        pWnd = pWnd->GetNextWindow();
    }
    // å°†å¯¹è¯æ¡†å±…中
    GetWindowRect(&dlgRect);
    int dlgWidth = dlgRect.Width() * 2;
    int dlgHeight = dlgRect.Height() * 2;
    if (dlgWidth > screenRect.Width()) {
        dlgWidth = screenRect.Width();
    }
    if (dlgHeight > screenRect.Height()) {
        dlgHeight = screenRect.Height();
    }
    int centerX = screenRect.left + (screenRect.Width() - dlgWidth) / 2;
    int centerY = screenRect.top + (screenRect.Height() - dlgHeight) / 2;
    MoveWindow(centerX, centerY, dlgWidth, dlgHeight);
    return TRUE;
}
void CBaseDlg::OnSize(UINT nType, int cx, int cy)
{
    CDialogEx::OnSize(nType, cx, cy);
    if (nType == SIZE_MINIMIZED || m_mapCtrlLayouts.empty()) {
        return;
    }
    // æ£€æŸ¥å°ºå¯¸å˜åŒ–是否足够大,避免频繁调整
    //static int lastWidth = 0, lastHeight = 0;
    //if (abs(cx - lastWidth) < 10 && abs(cy - lastHeight) < 10) {
    //    return;
    //}
    //lastWidth = cx;
    //lastHeight = cy;
    // è®¡ç®—比例并调整布局
    float dScaleX = static_cast<float>(cx) / m_nInitialWidth;
    float dScaleY = static_cast<float>(cy) / m_nInitialHeight;
    AdjustControls(dScaleX, dScaleY);
}
void CBaseDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
    lpMMI->ptMinTrackSize.x = 400;
    lpMMI->ptMinTrackSize.y = 300;
    CDialogEx::OnGetMinMaxInfo(lpMMI);
}
HBRUSH CBaseDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    if (g_currentTheme) {
        pDC->SetBkColor(g_currentTheme->backgroundColor);
        pDC->SetTextColor(g_currentTheme->textColor);
        // è¿”回背景画刷
        return m_hBrush;
    }
    return CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
}
SourceCode/Bond/BoounionPLC/CBaseDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,64 @@
#pragma once
#include <map>
#include <memory>
#include <unordered_map>
enum class ThemeType {
    Light,  // æµ…色主题
    Dark    // æ·±è‰²ä¸»é¢˜
};
struct Theme {
    COLORREF backgroundColor;
    COLORREF textColor;
    COLORREF buttonColor;
    COLORREF borderColor;
};
class CBaseDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CBaseDlg)
public:
    CBaseDlg(UINT nID, CWnd* pPage);            // æ ‡å‡†æž„造函数
    virtual ~CBaseDlg();                        // æžæž„函数
    // ä¸»é¢˜ç®¡ç†
    void SwitchTheme(ThemeType enThemeType);            // åˆ‡æ¢ä¸»é¢˜
    // èµ„源管理
    void LoadResourceLibrary(const CString& strLanguage);            // åŠ è½½èµ„æºåº“
    void UnloadResourceLibrary();                                    // å¸è½½èµ„源库
    // å­—体管理
    CFont* GetOrCreateFont(int nFontSize);            // èŽ·å–æˆ–åˆ›å»ºå­—ä½“
    void SetDefaultFont();                            // è®¾ç½®é»˜è®¤å­—体
    // åŠ¨æ€æŽ§ä»¶ç®¡ç†
    BOOL AddControl(UINT nCtrlID, CWnd* pControl);                    // æ·»åŠ æŽ§ä»¶
    BOOL RemoveControl(UINT nCtrlID);                                // ç§»é™¤æŽ§ä»¶
    BOOL UpdateControlText(UINT nCtrlID, const CString& strText);   // æ›´æ–°æŽ§ä»¶æ–‡æœ¬
    CWnd* GetControl(UINT nCtrlID);                                    // èŽ·å–æŽ§ä»¶
private:
    void AdjustControls(float dScaleX, float dScaleY);                // è°ƒæ•´æŽ§ä»¶å¤§å°
    void AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight);    // è°ƒæ•´æŽ§ä»¶å­—体
private:
    UINT m_nID;                                                    // å¯¹è¯æ¡†ID
    CWnd* m_pParent;                                            // çˆ¶çª—口
    HBRUSH m_hBrush;
    bool m_bResizing;                                            // æŽ§ä»¶æ˜¯å¦æ­£åœ¨è°ƒæ•´å¤§å°
    int m_nInitialWidth;                                        // å¯¹è¯æ¡†åˆå§‹å®½åº¦
    int m_nInitialHeight;                                        // å¯¹è¯æ¡†åˆå§‹é«˜åº¦
    std::unordered_map<int, CRect> m_mapCtrlLayouts;            // æŽ§ä»¶å¸ƒå±€
    std::map<UINT, std::unique_ptr<CWnd>> m_mapControls;        // æŽ§ä»¶é›†åˆ
    std::unordered_map<int, std::shared_ptr<CFont>> m_mapFonts;    // æŽ§ä»¶å­—体
    DECLARE_MESSAGE_MAP()
public:
    virtual BOOL OnInitDialog();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};
SourceCode/Bond/BoounionPLC/CPageLogcat.cpp
@@ -302,3 +302,13 @@
    m_bIncludeRegex = pCheckBox->GetCheck();
    theApp.m_model.m_configuration.setLogcatIncludeRegex(m_bIncludeRegex);
}
BOOL CPageLogcat::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) {
        return TRUE;
    }
    return CDialogEx::PreTranslateMessage(pMsg);
}
SourceCode/Bond/BoounionPLC/CPageLogcat.h
@@ -53,4 +53,5 @@
    afx_msg void OnButtonIncludeMenuClicked(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg void OnEnChangeEditInclude();
    afx_msg void OnBnClickedCheckRegex();
    virtual BOOL PreTranslateMessage(MSG* pMsg);
};
SourceCode/Bond/BoounionPLC/Common.h
@@ -1,5 +1,5 @@
#ifndef COMMON_H
#define COMMON_H
#pragma once
/* Rx Code */
#define RX_CODE_TEST                    0
@@ -80,9 +80,10 @@
#define BTN_OPR_FRAME_NORMAL            RGB(88, 88, 88)
#define BTN_OPR_FRAME_HOVER                RGB(88, 88, 88)
#define BTN_OPR_FRAME_PRESS                RGB(88, 88, 88)
#define BTN_OPR_BKGND_NORMAL            RGB(222, 222, 222)
#define BTN_OPR_BKGND_HOVER                RGB(208, 208, 222)
#define BTN_OPR_BKGND_PRESS                RGB(0, 232, 0)
#define BTN_OPR_BKGND_NORMAL            RGB(0, 168, 0)
#define BTN_OPR_BKGND_HOVER                RGB(255, 160, 64)
#define BTN_OPR_BKGND_PRESS                RGB(250, 155, 60)
#define BTN_OPR_BKGND_TEST                RGB(0, 255, 0)
/* å®šä½æŒ‰é’® */
#define BTN_POINT_FRAME_NORMAL            RGB(88, 88, 88)
@@ -125,5 +126,3 @@
/* ç›‘控数据id */
#define MONITOR_ID_ALARM        1001
#endif // COMMON_H
SourceCode/Bond/BoounionPLC/FileManager/AxisManager.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,297 @@
#include "stdafx.h"
#include <sstream>
#include <fstream>
#include <iostream>
#include "AxisManager.h"
#include "ToolUnits.h"
// æž„造函数
AxisManager::AxisManager() {
    m_directory = CToolUnits::getCurrentExePath() + _T("\\PLCs");
    if (!CToolUnits::isDirectory(m_directory)) {
        CToolUnits::createDir(m_directory.c_str());
    }
}
// åŠ è½½è½´ä¿¡æ¯
bool AxisManager::LoadAxes(pugi::xml_node axesNode) {
    m_axes.clear();
    for (auto axisNode : axesNode.children("Axis")) {
        AxisInfo axisInfo;
        axisInfo.id = axisNode.attribute("id").as_int();
        axisInfo.number = axisNode.attribute("number").value();
        axisInfo.description = axisNode.attribute("description").value();
        axisInfo.startAddress = axisNode.attribute("start_address").value();
        // åŠ è½½ ValueRange å€¼
        axisInfo.jogDistance = ValueRange(
            axisNode.child("jog_distance").attribute("min").as_double(),
            axisNode.child("jog_distance").attribute("max").as_double(),
            axisNode.child("jog_distance").attribute("current").as_double()
        );
        axisInfo.manualSpeed = ValueRange(
            axisNode.child("manual_speed").attribute("min").as_double(),
            axisNode.child("manual_speed").attribute("max").as_double(),
            axisNode.child("manual_speed").attribute("current").as_double()
        );
        axisInfo.autoSpeed = ValueRange(
            axisNode.child("auto_speed").attribute("min").as_double(),
            axisNode.child("auto_speed").attribute("max").as_double(),
            axisNode.child("auto_speed").attribute("current").as_double()
        );
        axisInfo.accelerationTime = ValueRange(
            axisNode.child("acceleration_time").attribute("min").as_double(),
            axisNode.child("acceleration_time").attribute("max").as_double(),
            axisNode.child("acceleration_time").attribute("current").as_double()
        );
        axisInfo.decelerationTime = ValueRange(
            axisNode.child("deceleration_time").attribute("min").as_double(),
            axisNode.child("deceleration_time").attribute("max").as_double(),
            axisNode.child("deceleration_time").attribute("current").as_double()
        );
        // åŠ è½½ PositionRange å€¼
        axisInfo.positioningPointCount = axisNode.child("Positions").attribute("positioningPointCount").as_int();
        for (auto positionNode : axisNode.child("Positions").children("Position")) {
            bool isEnable = positionNode.attribute("isEnable").as_bool();
            std::string description = positionNode.attribute("description").value();
            ValueRange positionRange(
                positionNode.attribute("min").as_double(),
                positionNode.attribute("max").as_double(),
                positionNode.attribute("current").as_double()
            );
            axisInfo.positions.emplace_back(PositionRange(isEnable, description, positionRange));
        }
        m_axes[axisInfo.id] = axisInfo;
    }
    return true;
}
// ä¿å­˜è½´ä¿¡æ¯
void AxisManager::SaveAxes(pugi::xml_node& axesNode) {
    for (const auto& axisEntry : m_axes) {
        const AxisInfo& axisInfo = axisEntry.second;
        auto axisNode = axesNode.append_child("Axis");
        axisNode.append_attribute("id") = axisInfo.id;
        axisNode.append_attribute("number") = axisInfo.number.c_str();
        axisNode.append_attribute("description") = axisInfo.description.c_str();
        axisNode.append_attribute("start_address") = axisInfo.startAddress.c_str();
        // ä¿å­˜ ValueRange å€¼
        auto jog_distance = axisNode.append_child("jog_distance");
        jog_distance.append_attribute("min") = axisInfo.jogDistance.minValue;
        jog_distance.append_attribute("max") = axisInfo.jogDistance.maxValue;
        jog_distance.append_attribute("current") = axisInfo.jogDistance.currentValue;
        auto manual_speed = axisNode.append_child("manual_speed");
        manual_speed.append_attribute("min") = axisInfo.manualSpeed.minValue;
        manual_speed.append_attribute("max") = axisInfo.manualSpeed.maxValue;
        manual_speed.append_attribute("current") = axisInfo.manualSpeed.currentValue;
        auto auto_speed = axisNode.append_child("auto_speed");
        auto_speed.append_attribute("min") = axisInfo.autoSpeed.minValue;
        auto_speed.append_attribute("max") = axisInfo.autoSpeed.maxValue;
        auto_speed.append_attribute("current") = axisInfo.autoSpeed.currentValue;
        auto acceleration_time = axisNode.append_child("acceleration_time");
        acceleration_time.append_attribute("min") = axisInfo.accelerationTime.minValue;
        acceleration_time.append_attribute("max") = axisInfo.accelerationTime.maxValue;
        acceleration_time.append_attribute("current") = axisInfo.accelerationTime.currentValue;
        auto deceleration_time = axisNode.append_child("deceleration_time");
        deceleration_time.append_attribute("min") = axisInfo.decelerationTime.minValue;
        deceleration_time.append_attribute("max") = axisInfo.decelerationTime.maxValue;
        deceleration_time.append_attribute("current") = axisInfo.decelerationTime.currentValue;
        // ä¿å­˜ PositionRange å€¼
        auto positionsNode = axisNode.append_child("Positions");
        positionsNode.append_attribute("positioningPointCount") = axisInfo.positioningPointCount;
        for (const auto& position : axisInfo.positions) {
            auto positionNode = positionsNode.append_child("Position");
            positionNode.append_attribute("isEnable") = position.isEnable;
            positionNode.append_attribute("description") = position.description.c_str();
            positionNode.append_attribute("min") = position.range.minValue;
            positionNode.append_attribute("max") = position.range.maxValue;
            positionNode.append_attribute("current") = position.range.currentValue;
        }
    }
}
// åŠ è½½é…æ–¹ï¼ˆå¦‚æžœæ–‡ä»¶ä¸å­˜åœ¨ï¼ŒåŠ è½½é»˜è®¤æ•°æ®ï¼‰
bool AxisManager::LoadAxis(const std::string& strName) {
    std::string filePath = m_directory + "\\" + strName + "\\" + "AxesConfiguration.xml";
    pugi::xml_document doc;
    if (!doc.load_file(filePath.c_str())) {
        std::cerr << "Recipe file not found: " << filePath << ". Loading default recipe." << std::endl;
        return false;
    }
    auto rootNode = doc.child("root");
    LoadAxes(rootNode);
    return true;
}
// ä¿å­˜é…æ–¹
bool AxisManager::SaveAxis(const std::string& strName) {
    // ç”Ÿæˆæ–‡ä»¶è·¯å¾„
    std::string filePath = m_directory + "\\" + strName + "\\" + "AxesConfiguration.xml";
    // åˆ›å»º XML æ–‡æ¡£å¯¹è±¡
    pugi::xml_document doc;
    // å¦‚果轴数据为空,生成默认配方
    if (m_axes.empty()) {
        GenerateDefaultData();
    }
    // æ·»åŠ è½´ä¿¡æ¯
    auto rootNode = doc.append_child("root");
    SaveAxes(rootNode);
    // ä¿å­˜ XML æ–‡ä»¶
    return doc.save_file(filePath.c_str());
}
// ç”Ÿæˆé»˜è®¤é…æ–¹
void AxisManager::GenerateDefaultData() {
    m_axes.clear();
    for (int axisId = 1; axisId <= 12; ++axisId) {
        AxisInfo axisInfo;
        axisInfo.id = axisId;
        axisInfo.positioningPointCount = 25;
        axisInfo.number = "M100-M" + std::to_string(axisId);
        axisInfo.description = "Default_Axis" + std::to_string(axisId);
        axisInfo.startAddress = "ZR" + std::to_string(10000 + (axisId - 1) * 300);
        // è®¾ç½®é»˜è®¤çš„ ValueRange
        axisInfo.jogDistance = ValueRange(1.0, 10.0, 1.0);
        axisInfo.manualSpeed = ValueRange(1.0, 100.0, 10.0);
        axisInfo.autoSpeed = ValueRange(5.0, 200.0, 50.0);
        axisInfo.accelerationTime = ValueRange(1.0, 10.0, 1.0);
        axisInfo.decelerationTime = ValueRange(1.0, 10.0, 1.0);
        // æ·»åŠ å®šä½ç‚¹å¹¶è®¾ç½®é»˜è®¤çš„æœ€å°å€¼å’Œæœ€å¤§å€¼
        for (int posId = 0; posId < axisInfo.positioningPointCount; ++posId) {
            double minPos = (posId + 1) * 5.0;
            double maxPos = (posId + 1) * 20.0;
            axisInfo.positions.emplace_back(PositionRange(TRUE, "Position " + std::to_string(posId + 1), ValueRange(minPos, maxPos, (posId + 1) * 10.0)));
        }
        m_axes[axisId] = axisInfo;
    }
}
// èŽ·å–æ‰€æœ‰è½´ä¿¡æ¯
const std::map<int, AxisInfo>& AxisManager::GetAxes() const {
    return m_axes;
}
// èŽ·å–å•ä¸ªè½´ä¿¡æ¯
AxisInfo AxisManager::GetAxis(int axisId) const {
    auto it = m_axes.find(axisId);
    if (it != m_axes.end()) {
        return it->second;  // å¦‚果找到了轴,返回其详细信息
    }
    // å¦‚果没有找到该轴,返回一个默认的无效 AxisInfo
    return AxisInfo{ -1, 0, /*0.0, 0.0,*/ "", "", "", ValueRange(), ValueRange(), ValueRange(), ValueRange(), ValueRange(), {} };
}
// æ›´æ–°è½´ä¿¡æ¯
bool AxisManager::UpdateAxis(const AxisInfo& axisInfo) {
    if (m_axes.find(axisInfo.id) == m_axes.end()) {
        return false; // è½´ä¸å­˜åœ¨
    }
    m_axes[axisInfo.id] = axisInfo;
    return true;
}
// æ·»åŠ æ–°çš„è½´ä¿¡æ¯
bool AxisManager::AddAxis(const AxisInfo& axisInfo) {
    if (m_axes.find(axisInfo.id) != m_axes.end()) {
        return false; // è½´å·²å­˜åœ¨
    }
    m_axes[axisInfo.id] = axisInfo;
    return true;
}
// åˆ é™¤è½´ä¿¡æ¯
bool AxisManager::DeleteAxis(int axisId) {
    return m_axes.erase(axisId) > 0;
}
// èŽ·å–æ‰€æœ‰è½´ç¼–å·
std::vector<int> AxisManager::GetAllAxisID() const {
    std::vector<int> axisNumbers;
    for (const auto& axis : m_axes) {
        int axisId = axis.first;
        axisNumbers.push_back(axisId);
    }
    return axisNumbers;
}
// èŽ·å–æŒ‡å®šé¡µçš„å®šä½ç‚¹
std::vector<PositionRange> AxisManager::GetPositions(int axisId, int pageNumber, int pageSize) const {
    std::vector<PositionRange> result;
    // æ£€æŸ¥è½´æ˜¯å¦å­˜åœ¨
    auto it = m_axes.find(axisId);
    if (it == m_axes.end()) {
        return result; // å¦‚果轴 ID ä¸å­˜åœ¨ï¼Œè¿”回空结果
    }
    // èŽ·å–æŒ‡å®šè½´çš„æ‰€æœ‰å®šä½ç‚¹
    const auto& positions = it->second.positions;
    // ç¡®å®šåˆ†é¡µèŒƒå›´
    int startIndex = (pageNumber - 1) * pageSize;
    int endIndex = startIndex + pageSize;
    // éåŽ†å®šä½ç‚¹ï¼ŒæŒ‰åˆ†é¡µæå–æ•°æ®
    int index = 0;
    for (const auto& pos : positions) {
        const PositionRange& position = pos;  // å®šä½ç‚¹åŒ…含描述、位置、最小值、最大值和当前值
        if (index >= startIndex && index < endIndex) {
            result.push_back(position);  // æ·»åŠ å®Œæ•´çš„ PositionRange å¯¹è±¡
        }
        ++index;
        if (index >= endIndex) {
            break; // è¾¾åˆ°åˆ†é¡µç»“束点
        }
    }
    return result;
}
// èŽ·å–æŒ‡å®šè½´çš„å®šä½ç‚¹
PositionRange AxisManager::GetPositionByIndex(int axisId, int pageNumber, int pageSize, int currentIndex) const {
    // æ£€æŸ¥è½´æ˜¯å¦å­˜åœ¨
    auto it = m_axes.find(axisId);
    if (it == m_axes.end()) {
        return PositionRange();  // è½´ä¸å­˜åœ¨ï¼Œè¿”回默认构造的 PositionRange(无效的定位点)
    }
    // èŽ·å–æŒ‡å®šè½´çš„æ‰€æœ‰å®šä½ç‚¹
    const auto& positions = it->second.positions;
    // ç¡®å®šåˆ†é¡µèŒƒå›´
    int startIndex = (pageNumber - 1) * pageSize;
    int endIndex = startIndex + pageSize;
    // å¦‚æžœ currentIndex è¶…过了当前页的范围,返回无效的 PositionRange
    if (currentIndex < 0 || currentIndex >= pageSize || currentIndex + startIndex >= positions.size()) {
        return PositionRange();  // è¿”回无效的定位点
    }
    // è¿”回指定定位点(考虑分页)
    return positions[startIndex + currentIndex];
}
SourceCode/Bond/BoounionPLC/FileManager/AxisManager.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
#ifndef RECIPE_MANAGER_H
#define RECIPE_MANAGER_H
#include <string>
#include <vector>
#include <map>
#include "pugixml.hpp"
struct ValueRange {
    double minValue;        // æœ€å°å€¼
    double maxValue;        // æœ€å¤§å€¼
    double currentValue;    // å½“前值
    // æž„造函数初始化
    ValueRange(double minVal = 0.0, double maxVal = 0.0, double curVal = 0.0)
        : minValue(minVal), maxValue(maxVal), currentValue(curVal) {}
};
struct PositionRange {
    BOOL isEnable;            // æ˜¯å¦å¯ç”¨
    std::string description;  // å®šä½ç‚¹æè¿°
    ValueRange range;         // ä½ç½®çš„æœ€å°å€¼ã€æœ€å¤§å€¼å’Œå½“前值
    // æž„造函数初始化
    PositionRange(BOOL b = TRUE, const std::string& desc = "", const ValueRange& r = ValueRange())
        :isEnable(b), description(desc), range(r) {}
};
// è½´ä¿¡æ¯ç»“构体
struct AxisInfo {
    int id;                                    // è½´ID
    int positioningPointCount;                 // å®šä½ç‚¹æ•°
    std::string number;                        // è½´ç¼–号
    std::string description;                   // è½´æè¿°
    std::string startAddress;                  // èµ·å§‹åœ°å€
    ValueRange jogDistance;                    // å¾®åŠ¨é‡ï¼ˆæœ€å°å€¼ã€æœ€å¤§å€¼ã€å½“å‰å€¼ï¼‰
    ValueRange manualSpeed;                    // æ‰‹åŠ¨é€Ÿåº¦ï¼ˆæœ€å°å€¼ã€æœ€å¤§å€¼ã€å½“å‰å€¼ï¼‰
    ValueRange autoSpeed;                      // è‡ªåŠ¨é€Ÿåº¦ï¼ˆæœ€å°å€¼ã€æœ€å¤§å€¼ã€å½“å‰å€¼ï¼‰
    ValueRange accelerationTime;               // åŠ é€Ÿæ—¶é—´ï¼ˆæœ€å°å€¼ã€æœ€å¤§å€¼ã€å½“å‰å€¼ï¼‰
    ValueRange decelerationTime;               // å‡é€Ÿæ—¶é—´ï¼ˆæœ€å°å€¼ã€æœ€å¤§å€¼ã€å½“前值)
    std::vector<PositionRange> positions;      // å®šä½ç‚¹ï¼šæè¿°ã€ä½ç½®åŠæœ€å°æœ€å¤§å€¼
};
// é…æ–¹ç®¡ç†ç±»
class AxisManager {
public:
    AxisManager();
    // åŠ è½½é…æ–¹ï¼ˆæ–‡ä»¶ä¸å­˜åœ¨æ—¶åŠ è½½é»˜è®¤æ•°æ®ï¼‰
    bool LoadAxis(const std::string& strName);
    // ä¿å­˜é…æ–¹
    bool SaveAxis(const std::string& strName);
    // ç”Ÿæˆé»˜è®¤é…æ–¹
    void GenerateDefaultData();
    // èŽ·å–æ‰€æœ‰è½´ä¿¡æ¯
    const std::map<int, AxisInfo>& GetAxes() const;
    // èŽ·å–å•ä¸ªè½´ä¿¡æ¯
    AxisInfo GetAxis(int axisId) const;
    // æ›´æ–°è½´ä¿¡æ¯
    bool UpdateAxis(const AxisInfo& axisInfo);
    // æ·»åŠ æ–°çš„è½´ä¿¡æ¯
    bool AddAxis(const AxisInfo& axisInfo);
    // åˆ é™¤è½´ä¿¡æ¯
    bool DeleteAxis(int axisId);
    // èŽ·å–æ‰€æœ‰è½´ID
    std::vector<int> GetAllAxisID() const;
    // èŽ·å–æŒ‡å®šé¡µçš„å®šä½ç‚¹
    std::vector<PositionRange> GetPositions(int axisId, int pageNumber, int pageSize) const;
    // èŽ·å–æŒ‡å®šé¡µçš„å®šä½ç‚¹
    PositionRange GetPositionByIndex(int axisId, int pageNumber, int pageSize, int currentIndex) const;
private:
    // è½´åŠ è½½å’Œä¿å­˜å‡½æ•°
    bool LoadAxes(pugi::xml_node axesNode);
    void SaveAxes(pugi::xml_node& axesNode);
private:
    std::string m_directory;         // æ–‡ä»¶å¤¹è·¯å¾„
    std::map<int, AxisInfo> m_axes;  // è½´ä¿¡æ¯ç¼“å­˜
};
#endif // RECIPE_MANAGER_H
SourceCode/Bond/BoounionPLC/Model.cpp
@@ -5,7 +5,7 @@
#include "ToolUnits.h"
// å¸¸é‡
#define ADDR_NIGHT_SHIFT_CAPACTITY        2027
CModel* g_pModel = NULL;
void CALLBACK ModerTimerProc(HWND hWnd, UINT nMsg, UINT nTimerid, DWORD dwTime)
@@ -313,6 +313,13 @@
            }
        }
    }
    // è¯»å–产能信息
    CPLC* pPlc = getCurrentPlc();
    if (pPlc != nullptr) {
        pPlc->readPLCDataRegularly();
    }
}
std::map<std::string, CPLC*>& CModel::getPlcMap()
@@ -324,7 +331,32 @@
{
    auto iter = m_mapPlc.find(pszName);
    if (iter != m_mapPlc.end()) return -1;
    CString strPlcDir;
    strPlcDir.Format(_T("%s\\Plcs\\%s"), (LPTSTR)(LPCTSTR)m_strWorkDir, pszName);
    CPLC* pPLC = new CPLC(pszName, pszIp, port);
    pPLC->setWorkDir((LPTSTR)(LPCTSTR)strPlcDir);
    PLCListener listener;
    listener.onStateChanged = [&](void* pFrom, int state) -> void {
        LOGD("PLC状态改变,%d", state);
    };
    listener.onMonitorData = [&](void* pFrom, int id) -> void {
        LOGD("PLConMonitorData,%d", id);
    };
    listener.onAlarm = [&](void* pFrom, CAlarm* pAlarm, int flag) -> void {
        LOGE("onAlarm,%d %s", pAlarm->getId(), flag != 0 ? "ON" : "Off");
        if (flag == 1) {
            pAlarm->addRef();
            notifyObjAndPtr(RX_CODE_ALARM_ON, pAlarm, pFrom);
            pAlarm->release();
        }
        else {
            pAlarm->addRef();
            notifyObjAndPtr(RX_CODE_ALARM_OFF, pAlarm, pFrom);
            pAlarm->release();
        }
    };
    pPLC->setListener(listener);
    pPLC->init();
    m_mapPlc[pszName] = pPLC;
@@ -371,108 +403,4 @@
    }
    return nullptr;
}
void CModel::readPLCDataRegularly()
{
    CPLC* pPlc = getCurrentPlc();
    if (pPlc == nullptr || !pPlc->isConnected()) return;
    {
        auto funOnReadData = [this](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
            if (nDataSize == 2 && flag == 0) {
                int nVelocityRatio = CToolUnits::toInt16(&pData[0]);
                if (nVelocityRatio != m_nVelocityRatio) {
                    m_nVelocityRatio = nVelocityRatio;
                    notifyInt(RX_CODE_VELOCITY_RATIO, m_nVelocityRatio);
                }
            }
        };
        pPlc->readData(MC::D, 530, 2, funOnReadData);
    }
    {
        auto funOnReadData = [this](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
            if (nDataSize == 2 && flag == 0) {
                double dTactTime = (double)CToolUnits::toInt16(&pData[0]);
                if (dTactTime != m_dTactTime) {
                    m_dTactTime = dTactTime;
                    notifyDouble(RX_CODE_TACT_TIME, m_dTactTime);
                }
            }
        };
        pPlc->readData(MC::ZR, 1500, 2, funOnReadData);
    }
    {
        auto funOnReadData = [this](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
            if (nDataSize == (ADDR_NIGHT_SHIFT_CAPACTITY - 2012 + 1) * 2 && flag == 0) {
                int nDayShiftCapacity = CToolUnits::toInt16(&pData[0]);
                int nNightShiftCapacity = CToolUnits::toInt16(&pData[(ADDR_NIGHT_SHIFT_CAPACTITY - 2012) * 2]);
                if (nDayShiftCapacity != m_nDayShiftCapacity) {
                    m_nDayShiftCapacity = nDayShiftCapacity;
                    notifyInt(RX_CODE_DAY_SHIFT_CAPACTITY, nDayShiftCapacity);
                }
                if (nNightShiftCapacity != m_nNightShiftCapacity) {
                    m_nNightShiftCapacity = nNightShiftCapacity;
                    notifyInt(RX_CODE_NIGHT_SHIFT_CAPACTITY, nNightShiftCapacity);
                }
            }
        };
        pPlc->readData(MC::ZR, 2012, (ADDR_NIGHT_SHIFT_CAPACTITY - 2012 + 1) * 2, funOnReadData);
    }
    {
        int nStartAddress = 1000;
        int nEndAddress = 1200;
        int nReadSize = (nEndAddress - nStartAddress + 1) * 2;
        auto funOnReadData = [this, nStartAddress, nReadSize](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
            if (nDataSize == nReadSize && flag == 0) {
                bool bRun = CToolUnits::toInt16(&pData[(1103 - nStartAddress) * 2]) != 0;        // å¯åЍ
                bool bAuto = CToolUnits::toInt16(&pData[(1100 - nStartAddress) * 2]) != 0;        // è‡ªåЍ
                bool bPuase = CToolUnits::toInt16(&pData[(1104 - nStartAddress) * 2]) != 0;        // æš‚停
                bool bManual = CToolUnits::toInt16(&pData[(1100 - nStartAddress) * 2]) != 0;    // æ‰‹åЍ
                bool bBeep = CToolUnits::toInt16(&pData[(1003 - nStartAddress) * 2]) != 0;        // é™éŸ³
                bool bResetting = CToolUnits::toInt16(&pData[(1150 - nStartAddress) * 2]) != 0; // å¤ä½
                bool bStop = CToolUnits::toInt16(&pData[(1114 - nStartAddress) * 2]) != 0;        // Í£Ö¹
                if (m_bBlBtnsStates[0] != bRun) {
                    m_bBlBtnsStates[0] = bRun;
                    notifyInt(RX_CODE_ACTIVATE, bRun);
                }
                if (m_bBlBtnsStates[1] != bAuto) {
                    m_bBlBtnsStates[1] = bAuto;
                    notifyInt(RX_CODE_AUTO, bAuto);
                }
                if (m_bBlBtnsStates[2] != bPuase) {
                    m_bBlBtnsStates[2] = bPuase;
                    notifyInt(RX_CODE_PUASE, bPuase);
                }
                if (m_bBlBtnsStates[3] != bManual) {
                    m_bBlBtnsStates[3] = bManual;
                    notifyInt(RX_CODE_MANUAL, bManual);
                }
                if (m_bBlBtnsStates[4] != bBeep) {
                    m_bBlBtnsStates[4] = bBeep;
                    notifyInt(RX_CODE_BEEP, bBeep);
                }
                if (m_bBlBtnsStates[5] != bResetting) {
                    m_bBlBtnsStates[5] = bResetting;
                    notifyInt(RX_CODE_RESETTING, bResetting);
                }
                if (m_bBlBtnsStates[6] != bStop) {
                    m_bBlBtnsStates[6] = bStop;
                    notifyInt(RX_CODE_STOP, bStop);
                }
            }
        };
        pPlc->readData(MC::M, nStartAddress, nReadSize, funOnReadData);
    }
}
SourceCode/Bond/BoounionPLC/Model.h
@@ -38,18 +38,8 @@
    int notifyTextAndInt(int code, const char* pszText, int exCode);
    int notifyMesMsg(int code, int stream, int function, const char* pszText);
private:
    void readPLCDataRegularly();
public:
    CConfiguration m_configuration;
private:
    int m_nVelocityRatio;        // é€Ÿåº¦æ¯”
    double m_dTactTime;            // å‘¨æœŸæ—¶é—´
    int m_nDayShiftCapacity;    // ç™½ç­äº§èƒ½
    int m_nNightShiftCapacity;    // å¤œç­äº§èƒ½
    bool m_bBlBtnsStates[7];    // PLC View按钮状态
private:
    IObservable* m_pObservable;
SourceCode/Bond/BoounionPLC/PLC.cpp
@@ -1,7 +1,10 @@
#include "stdafx.h"
#include "PLC.h"
#include "Log.h"
#include "ToolUnits.h"
#define ADDR_NIGHT_SHIFT_CAPACTITY        1627
void CALLBACK TimerFileProc(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
@@ -31,6 +34,9 @@
    m_nTimerId = 0;
    m_hTimeEvent = nullptr;
    m_bMute = false;
    m_pPlcData = new char[4096];
    m_nVelocityRatio = 0;
    InitializeCriticalSection(&m_criticalSection);
}
CPLC::CPLC(const char* pszName, const char* pszIp, const unsigned int port)
@@ -42,6 +48,7 @@
    m_state = PLCSTATE::READY;
    m_listener.onStateChanged = nullptr;
    m_listener.onMonitorData = nullptr;
    m_listener.onAlarm = nullptr;
    m_nUnHeartBeat = 0;
    m_hTimeEvent = nullptr;
    m_hMcMonitorStop = nullptr;
@@ -49,10 +56,32 @@
    m_mcMonitorThrdaddr = 0;
    m_nTimerId = 0;
    m_hTimeEvent = nullptr;
    m_pPlcData = new char[4096];
    m_nVelocityRatio = 0;
    m_dTactTime = 0.0;
    m_nDayShiftCapacity = 0;
    m_nNightShiftCapacity = 0;
    for (int i = 0; i < 7; i++) {
        m_bBlBtnsStates[i] = false;
    }
    InitializeCriticalSection(&m_criticalSection);
}
CPLC::~CPLC()
{
    if (m_pPlcData != nullptr) {
        delete[] m_pPlcData;
        m_pPlcData = nullptr;
    }
    DeleteCriticalSection(&m_criticalSection);
}
void CPLC::setListener(PLCListener& listener)
{
    m_listener.onStateChanged = listener.onStateChanged;
    m_listener.onMonitorData = listener.onMonitorData;
    m_listener.onAlarm = listener.onAlarm;
}
void CPLC::setWorkDir(const char* pszDir)
@@ -82,7 +111,32 @@
CAlarmMonitor* CPLC::getAlarmMonitor()
{
    return (CAlarmMonitor*)getComponent("PLC(1)");
    return (CAlarmMonitor*)getComponent("警告信息");
}
int CPLC::addMonitor(int id, int beginAddr, int endAddr, MC::SOFT_COMPONENT softComponent, char* pszRecvBuffer)
{
    // æ£€æŸ¥æ˜¯å¦æœ‰é‡å¤çš„
    Lock();
    for (auto& m : m_monitors) {
        if (m.id == id) {
            Unlock();
            return -1;
        }
    }
    MONITOR m;
    memset(&m, 0, sizeof(MONITOR));
    m.id = id;
    m.beginAddr = beginAddr;
    m.readLen = (endAddr - beginAddr + 1) * 2;
    m.softComponent = softComponent;
    m.szRecvBuffer = pszRecvBuffer;
    m.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
    m_monitors.push_back(m);
    Unlock();
    return 0;
}
void CPLC::init()
@@ -127,11 +181,12 @@
        m_pChannel->setChannelListener(&m_mcChannellistener);
        m_pChannel->setActionInterval(m_nActionInterval);
    }
    addMonitor(MONITOR_ID_ALARM, 10001, 10064, MC::SOFT_COMPONENT::M, &m_pPlcData[600]);
    // è­¦å‘Šç›‘控
    CString strAlarmFile;
    strAlarmFile.Format(_T("%s\\%s\\AlarmList.txt"), m_strWorkDir.c_str(), m_strName.c_str());
    strAlarmFile.Format(_T("%s\\AlarmList.txt"), m_strWorkDir.c_str());
    CAlarmMonitor* pAlarmMonitor = new CAlarmMonitor();
    pAlarmMonitor->setName("警告信息");
    pAlarmMonitor->setDescription("警告信息监控");
@@ -284,9 +339,24 @@
    WaitForSingleObject(monitor.hEvent, INFINITE);
    ResetEvent(monitor.hEvent);
    if (bReadOk) {
        ASSERT(m_listener.onMonitorData);
        onMonitorData(monitor);
    }
}
int CPLC::onMonitorData(MONITOR& monitor)
{
    // è½¬å‘到警告模块处理解释数据
    if (monitor.id == MONITOR_ID_ALARM) {
        for (auto c : m_components) {
            c->onData(monitor.id, monitor.szRecvBuffer, monitor.readLen);
        }
    }
    if (m_listener.onMonitorData) {
        m_listener.onMonitorData(this, monitor.id);
    }
    return 0;
}
int CPLC::readWord(MC::SOFT_COMPONENT softComponent, unsigned int addr,
@@ -368,3 +438,125 @@
    }
}
void CPLC::readPLCDataRegularly()
{
    if (!isConnected()) return;
    {
        auto funOnReadData = [this](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
            if (nDataSize == 2 && flag == 0) {
                int nVelocityRatio = CToolUnits::toInt16(&pData[0]);
                if (nVelocityRatio != m_nVelocityRatio) {
                    m_nVelocityRatio = nVelocityRatio;
                    //notifyInt(RX_CODE_VELOCITY_RATIO, m_nVelocityRatio);
                }
            }
        };
        readData(MC::D, 530, 2, funOnReadData);
    }
    {
        auto funOnReadData = [this](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
            if (nDataSize == 2 && flag == 0) {
                double dTactTime = (double)CToolUnits::toInt16(&pData[0]);
                if (dTactTime != m_dTactTime) {
                    m_dTactTime = dTactTime;
                    // notifyDouble(RX_CODE_TACT_TIME, m_dTactTime);
                }
            }
        };
        readData(MC::ZR, 1500, 2, funOnReadData);
    }
    {
        auto funOnReadData = [this](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
            if (nDataSize == (ADDR_NIGHT_SHIFT_CAPACTITY - 1612 + 1) * 2 && flag == 0) {
                int nDayShiftCapacity = CToolUnits::toInt16(&pData[0]);
                int nNightShiftCapacity = CToolUnits::toInt16(&pData[(ADDR_NIGHT_SHIFT_CAPACTITY - 1612) * 2]);
                if (nDayShiftCapacity != m_nDayShiftCapacity) {
                    m_nDayShiftCapacity = nDayShiftCapacity;
                    // notifyInt(RX_CODE_DAY_SHIFT_CAPACTITY, nDayShiftCapacity);
                }
                if (nNightShiftCapacity != m_nNightShiftCapacity) {
                    m_nNightShiftCapacity = nNightShiftCapacity;
                    // notifyInt(RX_CODE_NIGHT_SHIFT_CAPACTITY, nNightShiftCapacity);
                }
            }
        };
        readData(MC::ZR, 1612, (ADDR_NIGHT_SHIFT_CAPACTITY - 1612 + 1) * 2, funOnReadData);
    }
    {
        int nStartAddress = 1000;
        int nEndAddress = 1200;
        int nReadSize = (nEndAddress - nStartAddress + 1) * 2;
        auto funOnReadData = [this, nStartAddress, nReadSize](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
            if (nDataSize == nReadSize && flag == 0) {
                bool bRun = CToolUnits::toInt16(&pData[(1103 - nStartAddress) * 2]) != 0;        // å¯åЍ
                bool bAuto = CToolUnits::toInt16(&pData[(1100 - nStartAddress) * 2]) != 0;        // è‡ªåЍ
                bool bPuase = CToolUnits::toInt16(&pData[(1104 - nStartAddress) * 2]) != 0;        // æš‚停
                bool bManual = CToolUnits::toInt16(&pData[(1100 - nStartAddress) * 2]) != 0;    // æ‰‹åЍ
                bool bBeep = CToolUnits::toInt16(&pData[(1003 - nStartAddress) * 2]) != 0;        // é™éŸ³
                bool bResetting = CToolUnits::toInt16(&pData[(1150 - nStartAddress) * 2]) != 0; // å¤ä½
                bool bStop = CToolUnits::toInt16(&pData[(1114 - nStartAddress) * 2]) != 0;        // Í£Ö¹
                if (m_bBlBtnsStates[0] != bRun) {
                    m_bBlBtnsStates[0] = bRun;
                    // notifyInt(RX_CODE_ACTIVATE, bRun);
                }
                if (m_bBlBtnsStates[1] != bAuto) {
                    m_bBlBtnsStates[1] = bAuto;
                    // notifyInt(RX_CODE_AUTO, bAuto);
                }
                if (m_bBlBtnsStates[2] != bPuase) {
                    m_bBlBtnsStates[2] = bPuase;
                    // notifyInt(RX_CODE_PUASE, bPuase);
                }
                if (m_bBlBtnsStates[3] != bManual) {
                    m_bBlBtnsStates[3] = bManual;
                    // notifyInt(RX_CODE_MANUAL, bManual);
                }
                if (m_bBlBtnsStates[4] != bBeep) {
                    m_bBlBtnsStates[4] = bBeep;
                    // notifyInt(RX_CODE_BEEP, bBeep);
                }
                if (m_bBlBtnsStates[5] != bResetting) {
                    m_bBlBtnsStates[5] = bResetting;
                    // notifyInt(RX_CODE_RESETTING, bResetting);
                }
                if (m_bBlBtnsStates[6] != bStop) {
                    m_bBlBtnsStates[6] = bStop;
                    // notifyInt(RX_CODE_STOP, bStop);
                }
            }
        };
        readData(MC::M, nStartAddress, nReadSize, funOnReadData);
    }
}
int CPLC::getVelocityRatio()
{
    return m_nVelocityRatio;
}
double CPLC::getTackTime()
{
    return m_dTactTime;
}
int CPLC::getDayShiftCapacity()
{
    return m_nDayShiftCapacity;
}
int CPLC::getNightShiftCapacity()
{
    return m_nNightShiftCapacity;
}
SourceCode/Bond/BoounionPLC/PLC.h
@@ -5,6 +5,8 @@
#pragma comment(lib,"winmm")
#define ALARM_MONITOR        _T("警告信息")
typedef std::function<void(void* pFrom, int)> ONPLCSTATECHANGED;
typedef std::function<void(void* pFrom, int)> ONPLCMONITORDATA;
typedef std::function<void(void* pFrom, CAlarm*, int)> ONALARM;
@@ -42,6 +44,7 @@
    ~CPLC();
public:
    void setListener(PLCListener& listener);
    void setWorkDir(const char* pszDir);
    void init();
    void term();
@@ -66,15 +69,24 @@
    int writeDWord(MC::SOFT_COMPONENT softComponent, unsigned int addr, int value, ONWRITE funOnWrite);
    int writeBit(MC::SOFT_COMPONENT softComponent, unsigned int addr, BOOL bValue, ONWRITE funOnWrite);
    int writeData(MC::SOFT_COMPONENT softComponent, unsigned int addr, const char* pszData, unsigned int length, ONWRITE funOnWrite);
    void readPLCDataRegularly();
public:
    int getVelocityRatio();
    double getTackTime();
    int getDayShiftCapacity();
    int getNightShiftCapacity();
public:
    HANDLE m_hTimeEvent;
private:
    inline void Lock() { EnterCriticalSection(&m_criticalSection); }
    inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
    void setState(PLCSTATE state);
    void monitorReadData(MONITOR& monitor);
    CString& dataToHexString(const char* pData, const int size, CString& strOut);
    int onMonitorData(MONITOR& monitor);
private:
    std::string m_strWorkDir;
@@ -87,13 +99,22 @@
    unsigned int m_nActionInterval;
    unsigned int m_nUnHeartBeat;
    std::vector<CComponent*> m_components;
    char* m_pPlcData;
private:
    CRITICAL_SECTION m_criticalSection;
    std::vector<MONITOR> m_monitors;
    HANDLE m_hMcMonitorStop;
    HANDLE m_hMcMonitorThreadHandle;
    unsigned m_mcMonitorThrdaddr;
    MMRESULT m_nTimerId;
    bool m_bMute;
private:
    int m_nVelocityRatio;        // é€Ÿåº¦æ¯”
    double m_dTactTime;            // å‘¨æœŸæ—¶é—´
    int m_nDayShiftCapacity;    // ç™½ç­äº§èƒ½
    int m_nNightShiftCapacity;    // å¤œç­äº§èƒ½
    bool m_bBlBtnsStates[7];    // PLC View按钮状态
};
SourceCode/Bond/BoounionPLC/PlcView.cpp
@@ -45,6 +45,7 @@
    ON_BN_CLICKED(IDC_BUTTON_SOUND_OFF, &CPlcView::OnBnClickedButtonSoundOff)
    ON_BN_CLICKED(IDC_BUTTON_RESETTING, &CPlcView::OnBnClickedButtonResetting)
    ON_BN_CLICKED(IDC_BUTTON_STOP, &CPlcView::OnBnClickedButtonStop)
    ON_WM_TIMER()
END_MESSAGE_MAP()
// CComponentData1Dlg æ¶ˆæ¯å¤„理程序
@@ -275,6 +276,9 @@
    SetDlgItemText(IDC_EDIT_DAY_SHIFT_CAPACITY, _T("0"));
    SetDlgItemText(IDC_EDIT_NIGHT_SHIFT_CAPACITY, _T("0"));
    SetTimer(1, 1000, nullptr);
    return TRUE;  // return TRUE unless you set the focus to a control
                  // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
@@ -361,3 +365,21 @@
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    HandleOperation(OperationType::STOP);
}
void CPlcView::OnTimer(UINT_PTR nIDEvent)
{
    if (1 == nIDEvent) {
        ASSERT(m_pContext);
        CPLC* pPlc = ((CPLC*)m_pContext);
        CString strText;
        strText.Format(_T("%d %s"), pPlc->getVelocityRatio(), _T("%"));
        GetDlgItem(IDC_EDIT_VELOCITY_RATIO)->SetWindowText(strText);
        strText.Format(_T("%.2f"), pPlc->getTackTime() * 0.01);
        GetDlgItem(IDC_EDIT_TACT_TIME)->SetWindowText(strText);
        SetDlgItemInt(IDC_EDIT_DAY_SHIFT_CAPACITY, pPlc->getDayShiftCapacity());
        SetDlgItemInt(IDC_EDIT_NIGHT_SHIFT_CAPACITY, pPlc->getNightShiftCapacity());
    }
    CBaseView::OnTimer(nIDEvent);
}
SourceCode/Bond/BoounionPLC/PlcView.h
@@ -76,5 +76,6 @@
    afx_msg void OnBnClickedButtonSoundOff();
    afx_msg void OnBnClickedButtonResetting();
    afx_msg void OnBnClickedButtonStop();
    afx_msg void OnTimer(UINT_PTR nIDEvent);
};
SourceCode/Bond/BoounionPLC/RegexEdit.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,146 @@
#include "stdafx.h"
#include "RegexEdit.h"
#include <stdexcept>
IMPLEMENT_DYNAMIC(CRegexEdit, CEdit)
CRegexEdit::CRegexEdit()
{
    m_enRegexType = RegexType::Alphanumeric;
    m_dMinValue = LDBL_MIN;
    m_dMaxValue = LDBL_MAX;
}
CRegexEdit::~CRegexEdit()
{
}
void CRegexEdit::SetRegexType(RegexType enType)
{
    m_enRegexType = enType;
}
void CRegexEdit::SetCustomRegex(const std::string& strCustomRegex)
{
    m_strCustomRegex = strCustomRegex;
}
void CRegexEdit::SetValueRange(long double dMinValue, long double dMaxValue)
{
    m_dMinValue = dMinValue;
    m_dMaxValue = dMaxValue;
}
void CRegexEdit::SetCustomComparator(std::function<bool(const std::string&)> comparator)
{
    m_customComparator = comparator;
}
void CRegexEdit::SetInvalidInputCallback(std::function<void()> callback)
{
    m_invalidInputCallback = callback;
}
bool CRegexEdit::FindMatch(const std::string& pattern, std::string& foundText)
{
    CString currentText;
    GetWindowText(currentText);
    std::string text(CT2A(currentText.GetString()));
    std::regex regexPattern(pattern);
    std::smatch match;
    if (std::regex_search(text, match, regexPattern)) {
        foundText = match.str();
        return true;
    }
    return false;
}
void CRegexEdit::ReplaceMatch(const std::string& pattern, const std::string& replacement)
{
    CString currentText;
    GetWindowText(currentText);
    std::string text(CT2A(currentText.GetString()));
    std::regex regexPattern(pattern);
    std::string result = std::regex_replace(text, regexPattern, replacement);
    SetWindowText(CString(result.c_str()));
}
std::regex CRegexEdit::GetCurrentRegex() const
{
    switch (m_enRegexType)
    {
    case RegexType::Alphanumeric:
        return std::regex("^[a-zA-Z0-9]*$");        // å­—母和数字
    case RegexType::Letters:
        return std::regex("^[a-zA-Z]*$");           // åªå…è®¸å­—母
    case RegexType::Digits:
        return std::regex("^\\d*$");                // åªå…è®¸æ•°å­—
    case RegexType::Decimal:
        return std::regex("^[-+]?\\d+(\\.\\d+)?$"); // å…è®¸å°æ•°å’Œæ•´æ•°
    case RegexType::Custom:
        return std::regex(m_strCustomRegex);        // è‡ªå®šä¹‰æ­£åˆ™
    default:
        return std::regex(".*");                    // é»˜è®¤å…è®¸è¾“入任何内容
    }
}
bool CRegexEdit::IsValueInRange(const std::string& strText)
{
    try {
        if (m_enRegexType == RegexType::Digits || m_enRegexType == RegexType::Decimal) {
            if (strText.find('.') == std::string::npos) {
                int nValue = std::stoi(strText);
                return nValue >= static_cast<int>(m_dMinValue) && nValue <= static_cast<int>(m_dMaxValue);
            }
            else {
                double dValue = std::stod(strText);
                return dValue >= m_dMinValue && dValue <= m_dMaxValue;
            }
        }
    }
    catch (const std::invalid_argument&) {
        return false;
    }
    return true;
}
BEGIN_MESSAGE_MAP(CRegexEdit, CEdit)
    ON_WM_CHAR()
END_MESSAGE_MAP()
void CRegexEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    CEdit::OnChar(nChar, nRepCnt, nFlags);
    return;
    // å¤„理删除键和退格键
    if (nChar == VK_BACK || nChar == VK_DELETE) {
        CEdit::OnChar(nChar, nRepCnt, nFlags);
        return;
    }
    CString strCurrent;
    GetWindowText(strCurrent);
    // èŽ·å–å…‰æ ‡å½“å‰ä½ç½®
    int nStartChar, nEndChar;
    GetSel(nStartChar, nEndChar); // èŽ·å–å½“å‰é€‰åŒºçš„èµ·å§‹å’Œç»“æŸä½ç½®
    std::string strText(CT2A(strCurrent.GetBuffer()));
    strText.insert(strText.begin() + nStartChar, (char)nChar);
    bool bValid = m_customComparator ? m_customComparator(strText) : IsValueInRange(strText);
    if (std::regex_match(strText, GetCurrentRegex()) && bValid) {
        CEdit::OnChar(nChar, nRepCnt, nFlags);
    }
    else {
        if (m_invalidInputCallback) {
            m_invalidInputCallback();
        }
    }
}
SourceCode/Bond/BoounionPLC/RegexEdit.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
#if !defined(AFX_REGEXEDIT_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_)
#define AFX_REGEXEDIT_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include <afxwin.h>
#include <regex>
#include <functional>
#include <limits>
// æžšä¸¾ç±»åž‹ï¼šæ­£åˆ™è¡¨è¾¾å¼ç±»åž‹
enum class RegexType
{
    Alphanumeric,   // å…è®¸å­—母和数字
    Letters,        // åªå…è®¸å­—母
    Digits,         // åªå…è®¸æ•°å­—
    Decimal,        // å…è®¸å°æ•°å’Œæ•´æ•°
    Custom          // è‡ªå®šä¹‰æ­£åˆ™
};
class CRegexEdit : public CEdit
{
    DECLARE_DYNAMIC(CRegexEdit)
public:
    // æž„造与析构
    CRegexEdit();
    virtual ~CRegexEdit();
    // è®¾ç½®æ­£åˆ™ç±»åž‹
    void SetRegexType(RegexType enType);
    // è®¾ç½®è‡ªå®šä¹‰æ­£åˆ™è¡¨è¾¾å¼
    void SetCustomRegex(const std::string& strCustomRegex);
    // è®¾ç½®æ•°å€¼èŒƒå›´ï¼ˆæ•´æ•°æˆ–浮点)
    void SetValueRange(long double dMinValue, long double dMaxValue);
    // è®¾ç½®è‡ªå®šä¹‰æ¯”较函数
    void SetCustomComparator(std::function<bool(const std::string&)> comparator);
    // è®¾ç½®è¾“入不合法函数
    void SetInvalidInputCallback(std::function<void()> callback);
    // æŸ¥æ‰¾åŒ¹é…å†…容
    bool FindMatch(const std::string& pattern, std::string& foundText);
    // æ›¿æ¢åŒ¹é…å†…容
    void ReplaceMatch(const std::string& pattern, const std::string& replacement);
protected:
    // æ ¹æ®æžšä¸¾å€¼è¿”回对应的正则表达式
    std::regex GetCurrentRegex() const;
    // æ ¡éªŒè¾“入是否在指定范围内
    bool IsValueInRange(const std::string& strText);
protected:
    RegexType m_enRegexType;        // å½“前选中的正则类型
    std::string m_strCustomRegex;   // è‡ªå®šä¹‰æ­£åˆ™è¡¨è¾¾å¼
    long double m_dMinValue;        // æœ€å°å€¼
    long double m_dMaxValue;        // æœ€å¤§å€¼
    std::function<bool(const std::string&)> m_customComparator; // è‡ªå®šä¹‰æ¯”较函数
    std::function<void()> m_invalidInputCallback;               // ä¸åˆæ³•输入的回调函数
protected:
    void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
    DECLARE_MESSAGE_MAP()
};
#endif // !defined(AFX_REGEXEDIT_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_)
SourceCode/Bond/Servo/SecsTestDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
// SecsTestDlg.cpp : å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "Servo.h"
#include "SecsTestDlg.h"
#include "afxdialogex.h"
// CSecsTestDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CSecsTestDlg, CDialogEx)
CSecsTestDlg::CSecsTestDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_DIALOG_SECS_TEST, pParent)
{
}
CSecsTestDlg::~CSecsTestDlg()
{
}
void CSecsTestDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CSecsTestDlg, CDialogEx)
    ON_BN_CLICKED(IDC_BUTTON_S1F13, &CSecsTestDlg::OnBnClickedButtonS1f13)
    ON_BN_CLICKED(IDC_BUTTON_S1F1, &CSecsTestDlg::OnBnClickedButtonS1f1)
END_MESSAGE_MAP()
// CSecsTestDlg æ¶ˆæ¯å¤„理程序
void CSecsTestDlg::OnBnClickedButtonS1f1()
{
    theApp.m_model.m_hsmsPassive.requestAreYouThere();
}
void CSecsTestDlg::OnBnClickedButtonS1f13()
{
}
SourceCode/Bond/Servo/SecsTestDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
#pragma once
// CSecsTestDlg å¯¹è¯æ¡†
class CSecsTestDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CSecsTestDlg)
public:
    CSecsTestDlg(CWnd* pParent = NULL);   // æ ‡å‡†æž„造函数
    virtual ~CSecsTestDlg();
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_SECS_TEST };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnBnClickedButtonS1f13();
    afx_msg void OnBnClickedButtonS1f1();
};
SourceCode/Bond/x64/BoounionPLC/Debug/PLCs/Bonder1/AlarmList.txt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,227 @@
1,1,A单元_急停_01
2,1,A单元_急停_02
3,1,A单元_急停_03
4,1,A单元_MEO
10,1,B单元_急停_01
11,1,B单元_急停_02
12,1,B单元_急停_03
13,1,B单元_MEO
201,2,A单元-上腔体压合Z轴1异常
202,2,A单元-上腔体压合Z轴2异常
203,2,A单元-上腔体压合Z轴3异常
204,2,A单元-上腔体压合Z轴4异常
205,2,A单元-上腔体压合Z轴5异常
206,2,A单元-上腔体Z轴1异常
207,2,A单元-上腔体Z轴2异常
208,2,A单元-分离胶辊Z轴1异常
209,2,A单元-分离胶辊Z轴2异常
210,2,A单元-左侧分离胶辊X轴1异常
211,2,A单元-左侧分离胶辊X轴2异常
212,2,A单元-分离胶辊调节Z轴异常
213,2,A单元-下腔体Z轴异常
214,2,A单元-收膜旋转轴异常
215,2,A单元-放膜旋转轴异常
217,2,B单元-上腔体压合Z轴1异常
218,2,B单元-上腔体压合Z轴2异常
219,2,B单元-上腔体压合Z轴3异常
220,2,B单元-上腔体压合Z轴4异常
221,2,B单元-上腔体压合Z轴5异常
222,2,B单元-上腔体Z轴1异常
223,2,B单元-上腔体Z轴2异常
224,2,B单元-分离胶辊Z轴1异常
225,2,B单元-分离胶辊Z轴2异常
226,2,B单元-左侧分离胶辊X轴1异常
227,2,B单元-左侧分离胶辊X轴2异常
228,2,B单元-分离胶辊调节Z轴异常
229,2,B单元-下腔体Z轴异常
230,2,B单元-收膜旋转轴异常
231,2,B单元-放膜旋转轴异常
260,2,QD77MS16(U60)异常
261,2,QD77MS16(U62)异常
501,3,A单元-分离膜收膜压紧气缸异常
502,3,A单元-分离膜放膜压紧气缸异常
503,3,A单元-粘膜上升气缸异常
504,3,A单元-粘膜下降气缸异常
505,3,A单元-高粘上压紧气缸异常
506,3,A单元-高粘下压紧气缸异常
507,3,A单元-干泵气阀异常
508,3,A单元-腔体干泵与分子泵组合气阀异常
509,3,A单元-腔体分子泵气阀异常
510,3,A单元-腔体总破真空气阀异常
520,3,B单元-分离膜收膜压紧气缸异常
521,3,B单元-分离膜放膜压紧气缸异常
522,3,B单元-粘膜上升气缸异常
523,3,B单元-粘膜下降气缸异常
524,3,B单元-高粘上压紧气缸异常
525,3,B单元-高粘下压紧气缸异常
526,3,B单元-干泵气阀异常
527,3,B单元-腔体干泵与分子泵组合气阀异常
528,3,B单元-腔体分子泵气阀异常
529,3,B单元-腔体总破真空气阀异常
541,3,A单元-上腔体破真空异常
542,3,A单元-下腔体破真空异常
543,3,A单元-腔体干泵破真空异常
544,3,A单元-腔体分离泵破真空异常
556,3,B单元-上腔体破真空异常
557,3,B单元-下腔体破真空异常
558,3,B单元-腔体干泵破真空异常
559,3,B单元-腔体分离泵破真空异常
571,3,A单元-上腔体吸真空异常
572,3,A单元-下腔体吸真空异常
573,3,A单元-腔体干泵吸真空异常
574,3,A单元-腔体分离泵吸真空异常
586,3,B单元-上腔体吸真空异常
587,3,B单元-下腔体吸真空异常
588,3,B单元-腔体干泵吸真空异常
589,3,B单元-腔体分离泵吸真空异常
601,3,A单元-下腔体在籍异常
610,3,B单元-下腔体在籍异常
621,3,A单元-离心膜断料
622,3,A单元-离心膜转动异常
626,3,B单元-离心膜断料
627,3,B单元-离心膜转动异常
631,3,A单元-上腔体压合Z轴1绝对位置丢失
632,3,A单元-上腔体压合Z轴2绝对位置丢失
633,3,A单元-上腔体压合Z轴3绝对位置丢失
634,3,A单元-上腔体压合Z轴4绝对位置丢失
635,3,A单元-上腔体压合Z轴5绝对位置丢失
636,3,A单元-上腔体Z轴1绝对位置丢失
637,3,A单元-上腔体Z轴2绝对位置丢失
641,3,B单元-上腔体压合Z轴1绝对位置丢失
642,3,B单元-上腔体压合Z轴2绝对位置丢失
643,3,B单元-上腔体压合Z轴3绝对位置丢失
644,3,B单元-上腔体压合Z轴4绝对位置丢失
645,3,B单元-上腔体压合Z轴5绝对位置丢失
646,3,B单元-上腔体Z轴1绝对位置丢失
647,3,B单元-上腔体Z轴2绝对位置丢失
651,3,A单元-安全门异常
653,3,B单元-安全门异常
656,3,A单元-设备正压异常
657,3,A单元-离子风正压异常
661,3,B单元-设备正压异常
662,3,B单元-离子风正压异常
666,3,A单元-上腔体压合Z轴同步异常
667,3,A单元-上腔体Z轴同步异常
668,3,A单元-分离胶辊Z轴同步异常
669,3,A单元-分离胶辊X轴同步异常
671,3,B单元-上腔体压合Z轴同步异常
672,3,B单元-上腔体Z轴同步异常
673,3,B单元-分离胶辊Z轴同步异常
674,3,B单元-分离胶辊X轴同步异常
676,3,A单元-干泵处于非远程模式
677,3,A单元-干泵DVP未运行
678,3,A单元-干泵MBP未运行
679,3,A单元-干泵异常
680,3,A单元-干泵面板急停触发
683,3,B单元-干泵处于非远程模式
684,3,B单元-干泵DVP未运行
685,3,B单元-干泵MBP未运行
686,3,B单元-干泵异常
687,3,B单元-干泵面板急停触发
690,3,A单元-上腔体压合Z轴1过载报警
691,3,A单元-上腔体压合Z轴2过载报警
692,3,A单元-上腔体压合Z轴3过载报警
693,3,A单元-上腔体压合Z轴4过载报警
694,3,A单元-上腔体压合Z轴5过载报警
695,3,A单元-上腔体Z轴1过载报警
696,3,A单元-上腔体Z轴2过载报警
697,3,A单元-分离胶辊Z轴1过载报警
698,3,A单元-分离胶辊Z轴2过载报警
699,3,A单元-分离胶辊X轴1过载报警
700,3,A单元-分离胶辊X轴2过载报警
701,3,B单元-上腔体压合Z轴1过载报警
702,3,B单元-上腔体压合Z轴2过载报警
703,3,B单元-上腔体压合Z轴3过载报警
704,3,B单元-上腔体压合Z轴4过载报警
705,3,B单元-上腔体压合Z轴5过载报警
706,3,B单元-上腔体Z轴1过载报警
707,3,B单元-上腔体Z轴2过载报警
708,3,B单元-分离胶辊Z轴1过载报警
709,3,B单元-分离胶辊Z轴2过载报警
710,3,B单元-分离胶辊X轴1过载报警
711,3,B单元-分离胶辊X轴2过载报警
712,3,A单元-上腔体压合Z轴5轴间误差过大
713,3,A单元-上腔体Z轴2轴间误差过大
714,3,A单元-上腔体Z轴与上腔压合Z轴误差过大
717,3,B单元-上腔体压合Z轴5轴间误差过大
718,3,B单元-上腔体Z轴2轴间误差过大
719,3,B单元-上腔体Z轴与上腔压合Z轴误差过大
722,3,A单元-分子泵处于非远程模式
723,3,A单元-分子泵异常
724,3,B单元-分子泵处于非远程模式
725,3,B单元-分子泵异常
726,3,A单元-干泵抽真空异常
727,3,B单元-干泵抽真空异常
729,3,A单元-上腔体加热主控仪表异常
730,3,A单元-上腔体加热腔体温度异常
732,3,A单元-下腔体加热主控仪表异常
733,3,A单元-下腔体加热腔体温度异常
739,3,B单元-上腔体加热主控仪表异常
740,3,B单元-上腔体加热腔体温度异常
742,3,B单元-下腔体加热主控仪表异常
743,3,B单元-下腔体加热腔体温度异常
801,3,上游连接中断
802,3,下游连接中断
806,3,上游交握超时
807,3,下游交握超时
811,3,A单元-离子风异常
814,3,B单元-离子风异常
SourceCode/Bond/x64/BoounionPLC/Debug/PLCs/Bonder1/AxesConfiguration.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,411 @@
<?xml version="1.0"?>
<root>
    <Axis id="1" number="M100-M1" description="Default_Axis1" start_address="ZR10000">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
    <Axis id="2" number="M100-M2" description="Default_Axis2" start_address="ZR10300">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
    <Axis id="3" number="M100-M3" description="Default_Axis3" start_address="ZR10600">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
    <Axis id="4" number="M100-M4" description="Default_Axis4" start_address="ZR10900">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
    <Axis id="5" number="M100-M5" description="Default_Axis5" start_address="ZR11200">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
    <Axis id="6" number="M100-M6" description="Default_Axis6" start_address="ZR11500">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
    <Axis id="7" number="M100-M7" description="Default_Axis7" start_address="ZR11800">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
    <Axis id="8" number="M100-M8" description="Default_Axis8" start_address="ZR12100">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
    <Axis id="9" number="M100-M9" description="Default_Axis9" start_address="ZR12400">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
    <Axis id="10" number="M100-M10" description="Default_Axis10" start_address="ZR12700">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
    <Axis id="11" number="M100-M11" description="Default_Axis11" start_address="ZR13000">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
    <Axis id="12" number="M100-M12" description="Default_Axis12" start_address="ZR13300">
        <jog_distance min="1" max="10" current="1" />
        <manual_speed min="1" max="100" current="10" />
        <auto_speed min="5" max="200" current="50" />
        <acceleration_time min="1" max="10" current="1" />
        <deceleration_time min="1" max="10" current="1" />
        <Positions positioningPointCount="25">
            <Position isEnable="1" description="Position 1" min="5" max="20" current="10" />
            <Position isEnable="1" description="Position 2" min="10" max="40" current="20" />
            <Position isEnable="1" description="Position 3" min="15" max="60" current="30" />
            <Position isEnable="1" description="Position 4" min="20" max="80" current="40" />
            <Position isEnable="1" description="Position 5" min="25" max="100" current="50" />
            <Position isEnable="1" description="Position 6" min="30" max="120" current="60" />
            <Position isEnable="1" description="Position 7" min="35" max="140" current="70" />
            <Position isEnable="1" description="Position 8" min="40" max="160" current="80" />
            <Position isEnable="1" description="Position 9" min="45" max="180" current="90" />
            <Position isEnable="1" description="Position 10" min="50" max="200" current="100" />
            <Position isEnable="1" description="Position 11" min="55" max="220" current="110" />
            <Position isEnable="1" description="Position 12" min="60" max="240" current="120" />
            <Position isEnable="1" description="Position 13" min="65" max="260" current="130" />
            <Position isEnable="1" description="Position 14" min="70" max="280" current="140" />
            <Position isEnable="1" description="Position 15" min="75" max="300" current="150" />
            <Position isEnable="1" description="Position 16" min="80" max="320" current="160" />
            <Position isEnable="1" description="Position 17" min="85" max="340" current="170" />
            <Position isEnable="1" description="Position 18" min="90" max="360" current="180" />
            <Position isEnable="1" description="Position 19" min="95" max="380" current="190" />
            <Position isEnable="1" description="Position 20" min="100" max="400" current="200" />
            <Position isEnable="1" description="Position 21" min="105" max="420" current="210" />
            <Position isEnable="1" description="Position 22" min="110" max="440" current="220" />
            <Position isEnable="1" description="Position 23" min="115" max="460" current="230" />
            <Position isEnable="1" description="Position 24" min="120" max="480" current="240" />
            <Position isEnable="1" description="Position 25" min="125" max="500" current="250" />
        </Positions>
    </Axis>
</root>
SourceCode/Bond/x64/BoounionPLC/Debug/PLCs/Bonder1/IOConfiguration.iom
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,128 @@
X1000,Unit1_急停 EMO,Y1010,Unit1_四色灯-红
X1001,Unit1_总进气压力检,Y1011,Unit1_四色灯-黄
X1002,Unit1_伺服电柜烟感报警,Y1012,Unit1_四色灯-绿
X1003,Unit1_加热电柜烟感报警,Y1013,Unit1_四色灯-蓝
X1004,安全继电器检,Y1014,Unit1_蜂鸣器-1
X1005,,Y1015,Unit1_蜂鸣器-2
X1006,,Y1016,Unit1_蜂鸣器-3
X1007,Unit1_安全门磁检1,Y1017,Unit1_蜂鸣器-4
X1008,Unit1_安全门磁检2,Y1018,Unit1_机台照明
X1009,Unit1_安全门磁检3,Y1019,Unit1_安全门锁屏蔽
X100A,Unit1_安全门磁检4,Y101A,
X100B,Unit1_安全门磁检5,Y101B,
X100C,Unit1_安全门磁检6,Y101C,
X100D,Unit1_安全门锁检1,Y101D,Unit1_安全门锁1
X100E,Unit1_安全门锁检2,Y101E,Unit1_安全门锁2
X100F,Unit1_安全门锁检3,Y101F,Unit1_安全门锁3
X1020,Unit1_分子泵-Alam(8-14),Y1030,Unit1_分子泵启动(1-9)
X1021,Unit1_分子泵-远程/本地模式(7-15),Y1031,Unit1_分子泵联锁装置(2-10)
X1022,Unit1_分子泵-正常运行(4-12),Y1032,Unit1_分子泵通断插板阀
X1023,Unit1_分子泵通断插板阀原位,Y1033,Unit1_气囊通断阀
X1024,Unit1_分子泵通断插板阀到位,Y1034,
X1025,Unit1_腔体托片左气缸原位,Y1035,Unit1_腔体托片左气缸原位
X1026,Unit1_腔体托片左气缸到位,Y1036,Unit1_腔体托片左气缸到位
X1027,Unit1_腔体托片右气缸原位,Y1037,Unit1_腔体托片右气缸原位
X1028,Unit1_腔体托片右气缸到位,Y1038,Unit1_腔体托片右气缸到位
X1029,Unit1_门阀升降气缸原位,Y1039,Unit1_门阀升降气缸
X102A,Unit1_门阀升降气缸到位,Y103A,
X102B,Unit1_腔体破真空气阀原位,Y103B,Unit1_腔体破真空气阀
X102C,Unit1_腔体破真空气阀到位,Y103C,Unit1_分子泵排气阀
X102D,Unit1_下腔平台真空检,Y103D,Unit1_下腔平台吸真空
X102E,Unit1_分子泵排气阀原位,Y103E,Unit1_下腔平台破真空
X102F,Unit1_分子泵排气阀到位,Y103F,
X1040,Unit1_上加热已上电,Y1050,Unit1_上加热上电
X1041,Unit1_上主温控表报警,Y1051,Unit1_下加热上电
X1042,Unit1_上监控温控表报警1,Y1052,
X1043,Unit1_上监控温控表报警2,Y1053,
X1044,Unit1_上监控温控表报警3,Y1054,
X1045,Unit1_上监控温控表报警4,Y1055,
X1046,Unit1_上监控温控表报警5,Y1056,
X1047,Unit1_下加热已上电,Y1057,
X1048,Unit1_下主温控表报警,Y1058,
X1049,Unit1_下监控温控表报警1,Y1059,
X104A,Unit1_下监控温控表报警2,Y105A,
X104B,Unit1_下监控温控表报警3,Y105B,
X104C,Unit1_下监控温控表报警4,Y105C,
X104D,Unit1_下监控温控表报警5,Y105D,
X104E,,Y105E,
X104F,,Y105F,
X1060,Unit1_干泵-DVP运行检测-11,Y1070,Unit1_干泵-DVP启动-1
X1061,Unit1_干泵-MBP运行检测-12,Y1071,Unit1_干泵-MBP启动-2
X1062,Unit1_干泵-错误报警中-14,Y1072,Unit1_干泵-异常解除-3
X1063,Unit1_干泵-错误警告中-16,Y1073,
X1064,Unit1_干泵-远程/本地模式-18,Y1074,Unit1_氮气通断电磁阀1
X1065,Unit1_干泵-紧急停止中-20,Y1075,Unit1_氮气通断电磁阀2
X1066,,Y1076,Unit1_氮气通断电磁阀3
X1067,,Y1077,Unit1_氮气通断电磁阀4
X1068,,Y1078,Unit1_加热板水冷通断电磁阀1
X1069,,Y1079,Unit1_加热板水冷通断电磁阀2
X106A,,Y107A,Unit1_加热板水冷通断电磁阀3
X106B,,Y107B,Unit1_加热板水冷通断电磁阀4
X106C,,Y107C,Unit1_腔体底板通断电磁阀1
X106D,Unit1_水箱上液位检,Y107D,Unit1_腔体底板通断电磁阀2
X106E,Unit1_水箱中液位检,Y107E,Unit1_水箱进水阀
X106F,Unit1_水箱下液位检,Y107F,Unit1_水箱出水阀
X1080,Unit2_急停 EMO,Y1090,Unit2_四色灯-红
X1081,Unit2_总进气压力检,Y1091,Unit2_四色灯-黄
X1082,Unit2_伺服电柜烟感报警,Y1092,Unit2_四色灯-绿
X1083,Unit2_加热电柜烟感报警,Y1093,Unit2_四色灯-蓝
X1084,安全继电器检,Y1094,Unit2_蜂鸣器-1
X1085,,Y1095,Unit2_蜂鸣器-2
X1086,,Y1096,Unit2_蜂鸣器-3
X1087,Unit2_安全门磁检1,Y1097,Unit2_蜂鸣器-4
X1088,Unit2_安全门磁检2,Y1098,Unit2_机台照明
X1089,Unit2_安全门磁检3,Y1099,Unit2_安全门锁屏蔽
X108A,Unit2_安全门磁检4,Y109A,
X108B,Unit2_安全门磁检5,Y109B,
X108C,Unit2_安全门磁检6,Y109C,
X108D,Unit2_安全门锁检1,Y109D,Unit2_安全门锁1
X108E,Unit2_安全门锁检2,Y109E,Unit2_安全门锁2
X108F,Unit2_安全门锁检3,Y109F,Unit2_安全门锁3
X10A0,Unit2_分子泵-Alam(8-14),Y10B0,Unit2_分子泵启动(1-9)
X10A1,Unit2_分子泵-远程/本地模式(7-15),Y10B1,Unit2_分子泵联锁装置(2-10)
X10A2,Unit2_分子泵-正常运行(4-12),Y10B2,Unit2_分子泵通断插板阀
X10A3,,Y10B3,Unit2_气囊通断阀
X10A4,,Y10B4,
X10A5,Unit2_腔体托片左气缸原位,Y10B5,Unit2_腔体托片左气缸原位
X10A6,Unit2_腔体托片左气缸到位,Y10B6,Unit2_腔体托片左气缸到位
X10A7,Unit2_腔体托片右气缸原位,Y10B7,Unit2_腔体托片右气缸原位
X10A8,Unit2_腔体托片右气缸到位,Y10B8,Unit2_腔体托片右气缸到位
X10A9,Unit2_门阀升降气缸原位,Y10B9,Unit2_门阀升降气缸
X10AA,Unit2_门阀升降气缸到位,Y10BA,
X10AB,Unit2_腔体破真空气阀原位,Y10BB,Unit2_腔体破真空气阀
X10AC,Unit2_腔体破真空气阀到位,Y10BC,Unit2_分子泵排气阀
X10AD,Unit2_下腔平台真空检,Y10BD,Unit2_下腔平台吸真空
X10AE,Unit2_分子泵排气阀原位,Y10BE,Unit2_下腔平台破真空
X10AF,Unit2_分子泵排气阀到位,Y10BF,
X10C0,Unit2_上加热已上电,Y10D0,Unit2_上加热上电
X10C1,Unit2_上主温控表报警,Y10D1,Unit2_下加热上电
X10C2,Unit2_上监控温控表报警1,Y10D2,
X10C3,Unit2_上监控温控表报警2,Y10D3,
X10C4,Unit2_上监控温控表报警3,Y10D4,
X10C5,Unit2_上监控温控表报警4,Y10D5,
X10C6,Unit2_上监控温控表报警5,Y10D6,
X10C7,Unit2_下加热已上电,Y10D7,
X10C8,Unit2_下主温控表报警,Y10D8,
X10C9,Unit2_下监控温控表报警1,Y10D9,
X10CA,Unit2_下监控温控表报警2,Y10DA,
X10CB,Unit2_下监控温控表报警3,Y10DB,
X10CC,Unit2_下监控温控表报警4,Y10DC,
X10CD,Unit2_下监控温控表报警5,Y10DD,
X10CE,,Y10DE,
X10CF,,Y10DF,
X10E0,Unit2_干泵-DVP运行检测-11,Y10F0,Unit2_干泵-DVP启动-1
X10E1,Unit2_干泵-MBP运行检测-12,Y10F1,Unit2_干泵-MBP启动-2
X10E2,Unit2_干泵-错误报警中-14,Y10F2,Unit2_干泵-异常解除-3
X10E3,Unit2_干泵-错误警告中-16,Y10F3,
X10E4,Unit2_干泵-远程/本地模式-18,Y10F4,Unit2_氮气通断电磁阀1
X10E5,Unit2_干泵-紧急停止中-20,Y10F5,Unit2_氮气通断电磁阀2
X10E6,,Y10F6,Unit2_氮气通断电磁阀3
X10E7,,Y10F7,Unit2_氮气通断电磁阀4
X10E8,,Y10F8,Unit2_加热板水冷通断电磁阀1
X10E9,,Y10F9,Unit2_加热板水冷通断电磁阀2
X10EA,,Y10FA,Unit2_加热板水冷通断电磁阀3
X10EB,,Y10FB,Unit2_加热板水冷通断电磁阀4
X10EC,,Y10FC,Unit2_腔体底板通断电磁阀1
X10ED,Unit2_水箱上液位检,Y10FD,Unit2_腔体底板通断电磁阀2
X10EE,Unit2_水箱中液位检,Y10FE,Unit2_水箱进水阀
X10EF,Unit2_水箱下液位检,Y10FF,Unit2_水箱出水阀