chenluhua1980
2026-01-24 2a7efcf2a4bac5e7f9813975c87683ea09fb984e
SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
@@ -32,6 +32,28 @@
   {_T("SendPutAndHome"),       {true,  false, false, true,  true }}
};
std::map<CString, int> g_mapDeviceSlotCount = {
   {_T("Port1"), 8},
   {_T("Port2"), 8},
   {_T("Port3"), 8},
   {_T("Port4"), 8},
   {_T("RB1"), 1},
   {_T("RB2"), 1},
   {_T("AL"), 1},
   {_T("FLIP"), 1},
   {_T("Bonder1-上产品"), 1},
   {_T("Bonder1-下产品"), 1},
   {_T("Bonder2-上产品"), 1},
   {_T("Bonder2-下产品"), 1},
   {_T("VacBakeA腔"), 1},
   {_T("VacBakeB腔"), 1},
   {_T("BakecCoolingA烘烤"), 1},
   {_T("BakecCoolingA冷却"), 1},
   {_T("BakecCoolingB烘烤"), 1},
   {_T("BakecCoolingB冷却"), 1},
   {_T("Measurement"), 1}
};
// CRobotCmdTestDlg 对话框
IMPLEMENT_DYNAMIC(CRobotCmdTestDlg, CDialogEx)
@@ -64,8 +86,10 @@
}
BEGIN_MESSAGE_MAP(CRobotCmdTestDlg, CDialogEx)
   ON_CBN_SELCHANGE(IDC_COMBO_CMD_TYPE, &CRobotCmdTestDlg::OnCbnSelchangeComboCmdType)
   ON_BN_CLICKED(IDC_BUTTON_EXECUTE, &CRobotCmdTestDlg::OnBnClickedButtonExecute)
   ON_CBN_SELCHANGE(IDC_COMBO_CMD_TYPE, &CRobotCmdTestDlg::OnSelchangeComboCmdType)
   ON_CBN_SELCHANGE(IDC_COMBO_GET_POS, &CRobotCmdTestDlg::OnSelchangeComboGetPos)
   ON_CBN_SELCHANGE(IDC_COMBO_PUT_POS, &CRobotCmdTestDlg::OnSelchangeComboPutPos)
END_MESSAGE_MAP()
// CRobotCmdTestDlg 消息处理程序
@@ -81,11 +105,6 @@
   }
   m_comboCmdType.SetCurSel(0);
   // 初始化命令输入控件
   if (!g_mapQuickCmd.empty()) {
      UpdateCommandInputUI(g_mapQuickCmd.begin()->first);
   }
   // 初始化 Arm No(1:Arm#1,2:Arm#2)
   m_comboArmNo.AddString(_T("1"));
   m_comboArmNo.AddString(_T("2"));
@@ -93,19 +112,25 @@
   // 示例设备名称列表
   CStringList eqNameList;
   eqNameList.AddTail(_T("PORT 1"));            // 1 1 UNIT
   eqNameList.AddTail(_T("PORT 2"));            // 2 1 UNIT
   eqNameList.AddTail(_T("PORT 3"));            // 3 1 UNIT
   eqNameList.AddTail(_T("PORT 4"));            // 4 1 UNIT
   eqNameList.AddTail(_T("RB1"));               // 5 1 UNIT
   eqNameList.AddTail(_T("RB2"));               // 6 1 UNIT
   eqNameList.AddTail(_T("ALIGN"));            // 7 1 UNIT
   eqNameList.AddTail(_T("FLIP"));               // 8 1 UNIT
   eqNameList.AddTail(_T("VAC BAKE"));            // 9 2 UNIT
   eqNameList.AddTail(_T("BONDER1"));            // 10 2 UNIT
   eqNameList.AddTail(_T("BONDER2"));            // 11 2 UNIT
   eqNameList.AddTail(_T("POST BAKE(COOLING)"));   // 12 4 UNIT
   eqNameList.AddTail(_T("MEASUREMENT"));         // 13 1 UNIT
   eqNameList.AddTail(_T("Port1")); // 1
   eqNameList.AddTail(_T("Port2")); // 2
   eqNameList.AddTail(_T("Port3")); // 3
   eqNameList.AddTail(_T("Port4")); // 4
   eqNameList.AddTail(_T("RB1"));    // 5
   eqNameList.AddTail(_T("RB2"));    // 6
   eqNameList.AddTail(_T("AL"));    // 7
   eqNameList.AddTail(_T("FLIP"));    // 8
   eqNameList.AddTail(_T("Bonder1-上产品")); // 9
   eqNameList.AddTail(_T("Bonder1-下产品")); // 10
   eqNameList.AddTail(_T("Bonder2-上产品")); // 11
   eqNameList.AddTail(_T("Bonder2-下产品")); // 12
   eqNameList.AddTail(_T("VacBakeA腔"));     // 13
   eqNameList.AddTail(_T("VacBakeB腔"));     // 14
   eqNameList.AddTail(_T("BakecCoolingA烘烤")); // 15
   eqNameList.AddTail(_T("BakecCoolingA冷却")); // 16
   eqNameList.AddTail(_T("BakecCoolingB烘烤")); // 17
   eqNameList.AddTail(_T("BakecCoolingB冷却")); // 18
   eqNameList.AddTail(_T("Measurement"));       // 19
   for (POSITION pos = eqNameList.GetHeadPosition(); pos != NULL;) {
      CString item = eqNameList.GetNext(pos);
@@ -115,76 +140,77 @@
   m_comboGetPos.SetCurSel(0);
   m_comboPutPos.SetCurSel(0);
   // 初始化 Slot(默认从 1 到 25)
   for (int i = 1; i < 26; ++i) {
      CString str;
      str.Format(_T("%d"), i);
      m_comboGetSlot.AddString(str);
      m_comboPutSlot.AddString(str);
   // 初始化 Slot
   m_comboGetPos.SetCurSel(0);
   m_comboPutPos.SetCurSel(0);
   UpdateSlotList(&m_comboGetPos, &m_comboGetSlot);
   UpdateSlotList(&m_comboPutPos, &m_comboPutSlot);
   // 初始化命令输入控件
   if (!g_mapQuickCmd.empty()) {
      UpdateCommandInputUI(g_mapQuickCmd.begin()->first);
   }
   m_comboGetSlot.SetCurSel(0);
   m_comboPutSlot.SetCurSel(0);
   // 快捷命令执行映射表
   m_mapCmdExec = {
      {_T("SendHome"), [this](int seq, int, int, int, int, int) {
         return m_pEFEM->SendHome(seq);
      {_T("SendHome"), [this](int seq, int, int, int, int, int, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendHome(seq, onWritedBlock);
      }},
      {_T("SendTransfer"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
         return m_pEFEM->SendTransfer(seq, armNo, getPos, putPos, getSlot, putSlot);
      {_T("SendTransfer"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendTransfer(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
      }},
      {_T("SendMoveToGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
         return m_pEFEM->SendMoveToGet(seq, armNo, pos, slot);
      {_T("SendMoveToGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendMoveToGet(seq, armNo, pos, slot, onWritedBlock);
      }},
      {_T("SendMoveToPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
         return m_pEFEM->SendMoveToPut(seq, armNo, pos, slot);
      {_T("SendMoveToPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendMoveToPut(seq, armNo, pos, slot, onWritedBlock);
      }},
      {_T("SendGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
         return m_pEFEM->SendGet(seq, armNo, pos, slot);
      {_T("SendGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendGet(seq, armNo, pos, slot, onWritedBlock);
      }},
      {_T("SendPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
         return m_pEFEM->SendPut(seq, armNo, pos, slot);
      {_T("SendPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendPut(seq, armNo, pos, slot, onWritedBlock);
      }},
      {_T("SendExchange"), [this](int seq, int armNo, int pos, int, int getSlot, int putSlot) {
         return m_pEFEM->SendExchange(seq, armNo, pos, getSlot, putSlot);
      {_T("SendExchange"), [this](int seq, int armNo, int pos, int, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendExchange(seq, armNo, pos, getSlot, putSlot, onWritedBlock);
      }},
      {_T("SendCommandClear"), [this](int seq, int, int, int, int, int) {
         return m_pEFEM->SendCommandClear(seq);
      {_T("SendCommandClear"), [this](int seq, int, int, int, int, int, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendCommandClear(seq, onWritedBlock);
      }},
      {_T("SendBatchGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
         return m_pEFEM->SendBatchGet(seq, pos, slot);
      {_T("SendBatchGet"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendBatchGet(seq, pos, slot, onWritedBlock);
      }},
      {_T("SendBatchPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
         return m_pEFEM->SendBatchPut(seq, pos, slot);
      {_T("SendBatchPut"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendBatchPut(seq, pos, slot, onWritedBlock);
      }},
      {_T("SendMoveToGetAndHome"), [this](int seq, int armNo, int pos, int, int slot, int) {
         return m_pEFEM->SendMoveToGetAndHome(seq, armNo, pos, slot);
      {_T("SendMoveToGetAndHome"), [this](int seq, int armNo, int pos, int, int slot, int, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendMoveToGetAndHome(seq, armNo, pos, slot, onWritedBlock);
      }},
      {_T("SendMoveToPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot) {
         return m_pEFEM->SendMoveToPutAndHome(seq, armNo, pos, slot);
      {_T("SendMoveToPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendMoveToPutAndHome(seq, armNo, pos, slot, onWritedBlock);
      }},
      {_T("SendTransferAndHome"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
         return m_pEFEM->SendTransferAndHome(seq, armNo, getPos, putPos, getSlot, putSlot);
      {_T("SendTransferAndHome"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendTransferAndHome(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
      }},
      {_T("SendGetAndPut"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
         return m_pEFEM->SendGetAndPut(seq, armNo, getPos, putPos, getSlot, putSlot);
      {_T("SendGetAndPut"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendGetAndPut(seq, armNo, getPos, putPos, getSlot, putSlot, onWritedBlock);
      }},
      {_T("SendPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot) {
         return m_pEFEM->SendPutAndHome(seq, armNo, pos, slot);
      {_T("SendPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot, SERVO::ONWRITED onWritedBlock) {
         return m_pEFEM->robotSendPutAndHome(seq, armNo, pos, slot, onWritedBlock);
      }}
   };
@@ -204,11 +230,16 @@
   }
   const QuickCmdFieldMask& mask = it->second;
   GetDlgItem(IDC_COMBO_ARM_NO)->EnableWindow(mask.useArm);
   GetDlgItem(IDC_COMBO_GET_POS)->EnableWindow(mask.useGetPos);
   GetDlgItem(IDC_COMBO_GET_SLOT)->EnableWindow(mask.useGetSlot);
   GetDlgItem(IDC_COMBO_PUT_POS)->EnableWindow(mask.usePutPos);
   GetDlgItem(IDC_COMBO_PUT_SLOT)->EnableWindow(mask.usePutSlot);
   m_comboArmNo.SetCurSel(0);
   m_comboArmNo.EnableWindow(mask.useArm);
   m_comboGetPos.SetCurSel(0);
   m_comboGetPos.EnableWindow(mask.useGetPos);
   m_comboGetSlot.SetCurSel(0);
   m_comboGetSlot.EnableWindow(mask.useGetSlot);
   m_comboPutPos.SetCurSel(0);
   m_comboPutPos.EnableWindow(mask.usePutPos);
   m_comboPutSlot.SetCurSel(0);
   m_comboPutSlot.EnableWindow(mask.usePutSlot);
}
void CRobotCmdTestDlg::AppendLogLineBatchBegin()
@@ -239,6 +270,8 @@
void CRobotCmdTestDlg::AppendLogLineRichStyled(const CString& content, COLORREF color /*= RGB(0, 0, 0)*/)
{
   if (!::IsWindow(GetSafeHwnd())) return;
   // 时间戳
   CString timestamp;
   CTime now = CTime::GetCurrentTime();
@@ -296,19 +329,73 @@
   m_editLog.SetSel(-1, 0);
}
void CRobotCmdTestDlg::OnCbnSelchangeComboCmdType()
void CRobotCmdTestDlg::UpdateSlotList(CComboBox* pComboDevice, CComboBox* pComboSlot)
{
   int nSel = m_comboCmdType.GetCurSel();
   if (nSel < 0) {
   if (pComboDevice == nullptr || pComboSlot == nullptr) {
      return;
   }
   CString str;
   m_comboCmdType.GetLBText(nSel, str);
   UpdateCommandInputUI(str);
   int nSelIndex = pComboDevice->GetCurSel();
   if (nSelIndex < 0) {
      return;
   }
   str.Format(_T("切换当前命令类型:%s"), str);
   AppendLogLineRichStyled(str, LOG_COLOR_NORMAL);
   CString strDeviceName;
   pComboDevice->GetLBText(nSelIndex, strDeviceName);
   int nMaxSlot = 1; // 默认槽位数
   auto it = g_mapDeviceSlotCount.find(strDeviceName);
   if (it != g_mapDeviceSlotCount.end()) {
      nMaxSlot = it->second;
   }
   else {
      CString strLog;
      strLog.Format(_T("设备 %s 未定义槽位数,使用默认值 1"), strDeviceName.GetString());
      AppendLogLineRichStyled(strLog, LOG_COLOR_WARNING);
   }
   // 清空并添加槽号
   pComboSlot->ResetContent();
   for (int i = 1; i <= nMaxSlot; ++i) {
      CString str;
      str.Format(_T("%d"), i);
      pComboSlot->AddString(str);
   }
   pComboSlot->SetCurSel(0);
   pComboSlot->EnableWindow(1 != nMaxSlot);
}
void CRobotCmdTestDlg::UpdateArmList(CComboBox* pComboDevice, CComboBox* pComboArm)
{
   if (pComboDevice == nullptr || pComboArm == nullptr) {
      return;
   }
   int nSelIndex = pComboDevice->GetCurSel();
   if (nSelIndex < 0) {
      return;
   }
   CString strDeviceName;
   pComboDevice->GetLBText(nSelIndex, strDeviceName);
   if (IsDualArmSupported(strDeviceName)) {
      pComboArm->EnableWindow(TRUE);
   }
   else {
      pComboArm->EnableWindow(FALSE);
   }
   pComboArm->SetCurSel(0);
}
bool CRobotCmdTestDlg::IsDualArmSupported(const CString& strDeviceName)
{
   // 注意匹配规则是否区分“-上产品”、“-下产品”等后缀
   if (strDeviceName.Find(_T("FLIP")) >= 0) return true;
   if (strDeviceName.Find(_T("Bonder1")) >= 0) return true;
   if (strDeviceName.Find(_T("Bonder2")) >= 0) return true;
   return false;
}
void CRobotCmdTestDlg::OnBnClickedButtonExecute()
@@ -333,7 +420,16 @@
   // 查找函数并执行
   auto it = m_mapCmdExec.find(cmdName);
   if (it != m_mapCmdExec.end() && nullptr != m_pEFEM) {
      int ret = it->second(1, armNo, getPos, getSlot, putPos, putSlot);
      int ret = it->second(1, armNo, getPos, putPos, getSlot, putSlot, [&](int code) -> int {
         if (code == WOK) {
            AppendLogLineRichStyled(_T("已收到Robot回应!"), LOG_COLOR_SUCCESS);
         }
         else {
            AppendLogLineRichStyled(_T("未收到Robot回应!"), LOG_COLOR_ERROR);
         }
         return 0;
      });
      CString log;
      if (ret == 0) {
@@ -351,3 +447,32 @@
      AppendLogLineRichStyled(log, LOG_COLOR_ERROR);
   }
}
void CRobotCmdTestDlg::OnSelchangeComboCmdType()
{
   int nSel = m_comboCmdType.GetCurSel();
   if (nSel < 0) {
      return;
   }
   CString str;
   m_comboCmdType.GetLBText(nSel, str);
   UpdateCommandInputUI(str);
   str.Format(_T("切换当前命令类型:%s"), str);
   AppendLogLineRichStyled(str, LOG_COLOR_NORMAL);
}
void CRobotCmdTestDlg::OnSelchangeComboGetPos()
{
   // TODO: 在此添加控件通知处理程序代码
   UpdateSlotList(&m_comboGetPos, &m_comboGetSlot);
   UpdateArmList(&m_comboGetPos, &m_comboArmNo);
}
void CRobotCmdTestDlg::OnSelchangeComboPutPos()
{
   // TODO: 在此添加控件通知处理程序代码
   UpdateSlotList(&m_comboPutPos, &m_comboPutSlot);
   UpdateArmList(&m_comboPutPos, &m_comboArmNo);
}