From 8ffc831c6bf37a73961e22efc145be4e8c8f1241 Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期四, 19 六月 2025 10:05:07 +0800
Subject: [PATCH] Merge branch 'clh' into liuyang

---
 SourceCode/Bond/Servo/CEquipment.cpp |    2 
 SourceCode/Bond/Servo/CEFEM.cpp      |   19 ++++
 SourceCode/Bond/Servo/CMaster.cpp    |  117 +++++++++++++++++++++++++++++
 SourceCode/Bond/Servo/CMaster.h      |   10 ++
 SourceCode/Bond/Servo/CEquipment.h   |    2 
 SourceCode/Bond/Servo/ServoCommo.h   |    5 +
 SourceCode/Bond/Servo/ServoDlg.cpp   |   28 ++++++-
 SourceCode/Bond/Servo/Common.h       |    2 
 8 files changed, 175 insertions(+), 10 deletions(-)

diff --git a/SourceCode/Bond/Servo/CEFEM.cpp b/SourceCode/Bond/Servo/CEFEM.cpp
index c9f4f2e..d6a357d 100644
--- a/SourceCode/Bond/Servo/CEFEM.cpp
+++ b/SourceCode/Bond/Servo/CEFEM.cpp
@@ -611,7 +611,7 @@
 			CEqReadStep* pStep = new CEqReadStep(0x6301, 108 * 2,
 				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
 					if (code == ROK && pszData != nullptr && size > 0) {
-						decodePanelDataReport((CStep*)pFrom, pszData, size);
+						decodeFacDataReport((CStep*)pFrom, pszData, size);
 					}
 					return -1;
 				});
@@ -622,6 +622,23 @@
 				delete pStep;
 			}
 		}
+
+		{
+			// Panel Data Request xxx
+			CEqReadStep* pStep = new CEqReadStep(0x6301, 108 * 2,
+				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
+					if (code == ROK && pszData != nullptr && size > 0) {
+						decodeFacDataReport((CStep*)pFrom, pszData, size);
+					}
+					return -1;
+				});
+			pStep->setName(STEP_EQ_FAC_DATA_REPORT);
+			pStep->setProp("Port", (void*)1);
+			pStep->setWriteSignalDev(0x04d);
+			if (addStep(STEP_ID_PANEL_DATA_REQUEST, pStep) != 0) {
+				delete pStep;
+			}
+		}
 	}
 
 	// 必须要实现的虚函数,在此初始化Slot信息
diff --git a/SourceCode/Bond/Servo/CEquipment.cpp b/SourceCode/Bond/Servo/CEquipment.cpp
index ef24f61..2038e25 100644
--- a/SourceCode/Bond/Servo/CEquipment.cpp
+++ b/SourceCode/Bond/Servo/CEquipment.cpp
@@ -1021,7 +1021,7 @@
 
 		unsigned short operationMode = (unsigned short)((unsigned short)mode + getIndexerOperationModeBaseValue());
 		LOGI("<CEquipment-%s>准备设置indexerOperationMode<%d>", m_strName.c_str(), (int)mode);
-		pStep->writeShort(operationMode, [&, mode](int code) -> int {
+		pStep->writeShort(operationMode, [&, mode, onWritedRetBlock](int code) -> int {
 			int retCode = 0;
 			if (code == WOK) {
 				LOGI("<CEquipment-%s>设置indexerOperationMode成功.", m_strName.c_str());
diff --git a/SourceCode/Bond/Servo/CEquipment.h b/SourceCode/Bond/Servo/CEquipment.h
index 76e78b0..8108f02 100644
--- a/SourceCode/Bond/Servo/CEquipment.h
+++ b/SourceCode/Bond/Servo/CEquipment.h
@@ -43,7 +43,7 @@
 #define SIGNAL_UPSTREAM_TROUBLE	1
 #define SIGNAL_INTERLOCK		2
 #define SIGNAL_SEND_ABLE		3
-	typedef std::function<int(int writeCode, int retCode)> ONWRITEDRET;
+	typedef std::function<void(int writeCode, int retCode)> ONWRITEDRET;
 
 	typedef std::function<void(void* pEiuipment, BOOL bAlive)> ONALIVE;
 	typedef std::function<void(void* pEiuipment, int code)> ONDATACHANGED;
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index a751764..bcc0ea2 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -1,6 +1,8 @@
 #include "stdafx.h"
 #include "Common.h"
 #include "CMaster.h"
+#include <future>
+#include <vector>
 
 
 namespace SERVO {
@@ -48,6 +50,7 @@
 		m_ullRunTime = 0;
 		m_state = MASTERSTATE::READY;
 		m_pActiveRobotTask = nullptr;
+		m_nLastError = 0;
 		InitializeCriticalSection(&m_criticalSection);
 	}
 
@@ -264,6 +267,13 @@
 		return 0;
 	}
 
+	void CMaster::clearError()
+	{
+		m_nLastError = 0;
+		m_strLastError = "";
+		setState(MASTERSTATE::READY);
+	}
+
 	ULONGLONG CMaster::getRunTime()
 	{
 		if (m_state == MASTERSTATE::RUNNING)
@@ -325,8 +335,113 @@
 			// 如果状态为STARTING,开始工作并切换到RUNNING状态
 			lock();
 			if (m_state == MASTERSTATE::STARTING) {
+				// 发送indexerOperationModeChange到各个机台,成功后切换到RUNNING状态
+				// 否则切换到MSERROR状态
+				int nRet;
+				CEquipment* pEq[6] = { pEFEM, pBonder1, pBonder2, pBakeCooling, 
+					pVacuumBake, pMeasurement};
+				BOOL bIomcOk[7] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE};
+				std::vector<std::promise<void>> promises(6);
+				std::vector<std::future<void>> futures;
+
+				nRet = pEq[0]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
+					[&](int writeCode, int retCode) -> void {
+						bIomcOk[0] = retCode == (int)RET::OK;
+						promises[0].set_value();
+						TRACE("a0001\n", writeCode, retCode);
+					});
+				if (nRet != 0) {
+					LOGI("<Master>EFEM切换Start状态失败");
+					m_strLastError = "EFEM切换Start状态失败.";
+					goto WAIT;
+				}
+				futures.push_back(promises[0].get_future());
+
+				nRet = pEq[1]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
+					[&](int writeCode, int retCode) -> void {
+						bIomcOk[1] = retCode == (int)RET::OK;
+						promises[1].set_value();
+						TRACE("a0002\n");
+					});
+				if (nRet != 0) {
+					LOGI("<Master>Bonder1切换Start状态失败");
+					m_strLastError = "Bonder1切换Start状态失败.";
+					goto WAIT;
+				}
+				futures.push_back(promises[1].get_future());
+
+				nRet = pEq[2]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
+					[&](int writeCode, int retCode) -> void {
+						bIomcOk[2] = retCode == (int)RET::OK;
+						promises[2].set_value();
+						TRACE("a0003\n");
+					});
+				if (nRet != 0) {
+					LOGI("<Master>Bonder2切换Start状态失败");
+					m_strLastError = "Bonder2切换Start状态失败.";
+					goto WAIT;
+				}
+				futures.push_back(promises[2].get_future());
+
+				nRet = pEq[3]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
+					[&](int writeCode, int retCode) -> void {
+						bIomcOk[3] = retCode == (int)RET::OK;
+						promises[3].set_value();
+						TRACE("a0004\n");
+					});
+				if (nRet != 0) {
+					LOGI("<Master>BakeCooling切换Start状态失败");
+					m_strLastError = "BakeCooling切换Start状态失败.";
+					goto WAIT;
+				}
+				futures.push_back(promises[3].get_future());
+
+				nRet = pEq[4]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
+					[&](int writeCode, int retCode) -> void {
+						bIomcOk[4] = retCode == (int)RET::OK;
+						promises[4].set_value();
+						TRACE("a0005\n");
+					});
+				if (nRet != 0) {
+					LOGI("<Master>VacuumBake切换Start状态失败");
+					m_strLastError = "VacuumBake切换Start状态失败.";
+					goto WAIT;
+				}
+				futures.push_back(promises[4].get_future());
+
+				nRet = pEq[5]->indexerOperationModeChange(IDNEXER_OPERATION_MODE::Start,
+					[&](int writeCode, int retCode) -> void {
+						bIomcOk[5] = retCode == (int)RET::OK;
+						promises[5].set_value();
+						TRACE("a0006\n");
+					});
+				if (nRet != 0) {
+					LOGI("<Master>Measurement切换Start状态失败");
+					m_strLastError = "Measurement切换Start状态失败.";
+					goto WAIT;
+				}
+				futures.push_back(promises[5].get_future());
+
+WAIT:
+				for (auto& f : futures) {
+					f.wait();  // 阻塞等待对应设备完成
+				}
+				for (int i = 0; i < 6; i++) {
+					if (!bIomcOk[i]) {
+						bIomcOk[6] = FALSE;
+						LOGI("<Master>%s切换Start状态失败", pEq[i]->getName().c_str());
+					}
+				}
+				
+				// 检查看是否都已经切换到START状态
+				if (!bIomcOk[6]) {
+					unlock();
+					setState(MASTERSTATE::MSERROR);
+					continue;
+				}
+
+
 				unlock();
-				Sleep(1000);
 				setState(MASTERSTATE::RUNNING);
 				continue;
 			}
diff --git a/SourceCode/Bond/Servo/CMaster.h b/SourceCode/Bond/Servo/CMaster.h
index 2f8577d..28e2f5f 100644
--- a/SourceCode/Bond/Servo/CMaster.h
+++ b/SourceCode/Bond/Servo/CMaster.h
@@ -16,11 +16,12 @@
 
 
 namespace SERVO {
-    enum MASTERSTATE {
+    enum class MASTERSTATE {
         READY = 0,
         STARTING,
         RUNNING,
-        STOPPING
+        STOPPING,
+        MSERROR
     };
 
     typedef std::function<void(void* pMaster, MASTERSTATE state)> ONMASTERSTATECHANGED;
@@ -55,6 +56,7 @@
         int term();
         int start();
         int stop();
+        void clearError();
         ULONGLONG getRunTime();
         MASTERSTATE getState();
         unsigned DispatchProc();
@@ -122,6 +124,10 @@
         // 当前任务和已完成任务列表
         CRobotTask* m_pActiveRobotTask;
         std::list< CRobotTask* > m_listTask;
+
+        // 错误代码
+        int m_nLastError;
+        std::string m_strLastError;
     };
 }
 
diff --git a/SourceCode/Bond/Servo/Common.h b/SourceCode/Bond/Servo/Common.h
index 3a3055d..6a12cae 100644
--- a/SourceCode/Bond/Servo/Common.h
+++ b/SourceCode/Bond/Servo/Common.h
@@ -41,6 +41,7 @@
 #define CR_MSGBOX_MESSAGE					RGB(200, 216, 246)
 #define TOP_TOOLBAR_BACKGROUND				RGB(240, 240, 240)	
 #define STATUSBAR_BK_NORMAL					RGB(195, 195, 195)
+#define STATUSBAR_BK_STARTING				RGB(58, 127, 78)
 #define STATUSBAR_BK_RUNNING				RGB(34, 177, 76)
 #define STATUSBAR_BK_ALARM					RGB(255, 127, 39)
 
@@ -318,6 +319,7 @@
 #define STEP_ID_FETCHED_OUT_JOB_REPORT13		0x5BB
 #define STEP_ID_FETCHED_OUT_JOB_REPORT14		0x5BC
 #define STEP_ID_FETCHED_OUT_JOB_REPORT15		0x5BD
+#define STEP_ID_PANEL_DATA_REQUEST				0x5D0
 #define STEP_ID_PANEL_DATA_REPORT				0x5D1
 #define STEP_ID_IN_OP_CMD_REPLY					0x5F0
 #define STEP_ID_DISPATCHING_MODE_CHANGE_REPLY	0x5F1
diff --git a/SourceCode/Bond/Servo/ServoCommo.h b/SourceCode/Bond/Servo/ServoCommo.h
index 20e4434..979aabc 100644
--- a/SourceCode/Bond/Servo/ServoCommo.h
+++ b/SourceCode/Bond/Servo/ServoCommo.h
@@ -9,6 +9,11 @@
 #define SIGNAL_MAX					8
 #define ARM_ALL						99
 
+	enum class RET {
+		OK = 1,
+		NG,
+	};
+
 	enum class PortType {
 		Loading = 1,
 		Unloading,
diff --git a/SourceCode/Bond/Servo/ServoDlg.cpp b/SourceCode/Bond/Servo/ServoDlg.cpp
index 5fd7af6..bc56882 100644
--- a/SourceCode/Bond/Servo/ServoDlg.cpp
+++ b/SourceCode/Bond/Servo/ServoDlg.cpp
@@ -190,6 +190,18 @@
 					GetRuntimeFormatText(strText, "");
 					m_pMyStatusbar->setRunTimeText((LPTSTR)(LPCTSTR)strText);
 				}
+				else if (state == SERVO::MASTERSTATE::STARTING) {
+					m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_STARTING);
+					m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
+					m_pMyStatusbar->setRunTimeText("正在启动...");
+				}
+				else if (state == SERVO::MASTERSTATE::MSERROR) {
+					m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE);
+					m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
+					m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_ALARM);
+					m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0));
+					m_pMyStatusbar->setRunTimeText("启动失败.");
+				}
 				else if (state == SERVO::MASTERSTATE::RUNNING) {
 					m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
 					m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(TRUE);
@@ -856,14 +868,22 @@
 {
 	int id = (int)lParam;
 	if (id == IDC_BUTTON_RUN) {
-		theApp.m_model.getMaster().start();
-		m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
+		if (theApp.m_model.getMaster().getState() == SERVO::MASTERSTATE::MSERROR) {
+			AfxMessageBox("当前有机台发生错误,不能启动,请确认解决问题后再尝试重新启动!");
+		}
+		else {
+			if (theApp.m_model.getMaster().start() == 0) {
+				m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(FALSE);
+			}
+		}
 	}
 	else if (id == IDC_BUTTON_STOP) {
-		theApp.m_model.getMaster().stop();
-		m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
+		if (theApp.m_model.getMaster().stop() == 0) {
+			m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
+		}
 	}
 	else if (id == IDC_BUTTON_ROBOT) {
+		theApp.m_model.getMaster().clearError();
 		SERVO::CEFEM* pEFEM = (SERVO::CEFEM*)theApp.m_model.getMaster().getEquipment(EQ_ID_EFEM);
 		CRobotCmdTestDlg dlg;
 		dlg.SetEFEM(pEFEM);

--
Gitblit v1.9.3