From 8294c107676c18538c6e06fe8eab2d209604ac6a Mon Sep 17 00:00:00 2001
From: chenluhua1980 <Chenluhua@qq.com>
Date: 星期一, 19 一月 2026 18:34:06 +0800
Subject: [PATCH] 1.完善和优化界面显示,数据懒加载,等待光标等,修复启动时界面卡的问题。 2.SVData的Push的限制和检查,因发现Glass呆在机器中时,不管机台是否运行都在不停压入数据。

---
 SourceCode/Bond/Servo/CMaster.cpp |  421 ++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 305 insertions(+), 116 deletions(-)

diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index 6df6ca1..80ce726 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -3,10 +3,14 @@
 #include "CMaster.h"
 #include <future>
 #include <vector>
+#include <algorithm>
 #include "RecipeManager.h"
 #include <fstream>
 #include "SerializeUtil.h"
 #include "CServoUtilsTool.h"
+#include "AlarmManager.h"
+#include "ToolUnits.h"
+#include "Model.h"
 
 
 namespace SERVO {
@@ -71,6 +75,8 @@
 		m_nContinuousWorkingPort = 0;
 		m_nContinuousWorkingSlot = 0;
 		m_pControlJob = nullptr;
+		m_bPauseAlarmRaised = false;
+		m_pModelCtx = nullptr;
 		m_nTestFlag = 0;
 		InitializeCriticalSection(&m_criticalSection);
 	}
@@ -120,6 +126,11 @@
 		m_listener = listener;
 	}
 
+	void CMaster::setModelCtx(CModel* pModel)
+	{
+		m_pModelCtx = pModel;
+	}
+
 	CRobotTask* CMaster::getActiveRobotTask()
 	{
 		return m_pActiveRobotTask;
@@ -127,128 +138,147 @@
 
 	int CMaster::init()
 	{
+		const ULONGLONG boot_master_begin = GetTickCount64();
 		LOGI("<Master>姝e湪鍒濆鍖�...");
+		LOGI("[BOOT][MASTER] init begin");
 
 
 		// 	cclink
-		if (m_cclink.Connect(CC_LINK_IE_CONTROL_CHANNEL(1)) != 0) {
+		const ULONGLONG boot_cclink_begin = GetTickCount64();
+		const int cc_ret = m_cclink.Connect(CC_LINK_IE_CONTROL_CHANNEL(1));
+		LOGI("[BOOT][MASTER] CC-Link connect ret=%d, cost=%llu ms",
+			cc_ret,
+			(unsigned long long)(GetTickCount64() - boot_cclink_begin));
+		if (cc_ret != 0) {
 			LOGE("杩炴帴CC-Link澶辫触.");
 		}
 		else {
-			LOGI("杩炴帴CC-Link鎴愬姛.");
-			BoardVersion version{};
-			int nRet = m_cclink.GetBoardVersion(version);
-			if (nRet == 0) {
-				LOGD("鐗堟湰淇℃伅锛�%s.", version.toString().c_str());
-			}
-			else {
-				LOGE("鑾峰彇CC-Link鐗堟湰淇℃伅澶辫触.");
+				LOGI("杩炴帴CC-Link鎴愬姛.");
+				BoardVersion version{};
+				int nRet = m_cclink.GetBoardVersion(version);
+				if (nRet == 0) {
+					LOGD("鐗堟湰淇℃伅锛�%s.", version.toString().c_str());
+				}
+				else {
+					LOGE("鑾峰彇CC-Link鐗堟湰淇℃伅澶辫触.");
+				}
+
+				BoardStatus status;
+				nRet = m_cclink.GetBoardStatus(status);
+				if (nRet == 0) {
+					LOGD("鐘舵�侊細%s.", status.toString().c_str());
+				}
+				else {
+					LOGE("鑾峰彇CC-Link鐘舵�佸け璐�.");
+				}
 			}
 
-			BoardStatus status;
-			nRet = m_cclink.GetBoardStatus(status);
-			if (nRet == 0) {
-				LOGD("鐘舵�侊細%s.", status.toString().c_str());
+
+			// 鍒濆鍖栨坊鍔犲悇瀛愯澶�
+			CLoadPort* pPort1, * pPort2, * pPort3, * pPort4;
+			CBonder* pBonder1, * pBonder2;
+			CEFEM* pEfem;
+			CArm* pArm;
+			CArmTray* pArmTray1, * pArmTray2;
+			CFliper* pFliper;
+			CVacuumBake* pVacuumBake;
+			CAligner* pAligner;
+			CBakeCooling* pBakeCooling;
+			CMeasurement* pMeasurement;
+
+			pPort1 = addLoadPort(0);
+			pPort2 = addLoadPort(1);
+			pPort3 = addLoadPort(2);
+			pPort4 = addLoadPort(3);
+			pEfem = addEFEM();
+			pArm = addArm();
+			pArmTray1 = addArmTray(0);
+			pArmTray2 = addArmTray(1);
+			pFliper = addFliper();
+			pVacuumBake = addVacuumBake();
+			pAligner = addAligner();
+			pBonder1 = addBonder(0);
+			pBonder2 = addBonder(1);
+			pBakeCooling = addBakeCooling();
+			pMeasurement = addMeasurement();
+
+			ASSERT(pEfem);
+			ASSERT(pFliper);
+			ASSERT(pVacuumBake);
+			ASSERT(pAligner);
+			ASSERT(pBonder1);
+			ASSERT(pBonder2);
+			ASSERT(pBakeCooling);
+			ASSERT(pMeasurement);
+
+			pEfem->setPort(0, pPort1);
+			pEfem->setPort(1, pPort2);
+			pEfem->setPort(2, pPort3);
+			pEfem->setPort(3, pPort4);
+			pEfem->setFliper(pFliper);
+			pEfem->setAligner(pAligner);
+			pEfem->setArmTray(0, pArmTray1);
+			pEfem->setArmTray(1, pArmTray2);
+			pPort1->setArm(pArm);
+			pPort2->setArm(pArm);
+			pPort3->setArm(pArm);
+			pPort4->setArm(pArm);
+			pArmTray1->setArm(pArm);
+			pArmTray2->setArm(pArm);
+			pFliper->setArm(pArm);
+			pVacuumBake->setArm(pArm);
+			pAligner->setArm(pArm);
+			pBonder1->setArm(pArm);
+			pBonder2->setArm(pArm);
+			pBakeCooling->setArm(pArm);
+			pMeasurement->setArm(pArm);
+
+			connectEquipments();
+
+
+
+			// 璇荤紦瀛樻暟鎹�
+			const ULONGLONG boot_cache_begin = GetTickCount64();
+			const ULONGLONG boot_read_begin = GetTickCount64();
+			readCache();
+			LOGI("[BOOT][MASTER] readCache finished, cost=%llu ms", (unsigned long long)(GetTickCount64() - boot_read_begin));
+
+			const ULONGLONG boot_state_begin = GetTickCount64();
+			loadState();
+			LOGI("[BOOT][MASTER] loadState finished, cost=%llu ms", (unsigned long long)(GetTickCount64() - boot_state_begin));
+			if (m_listener.onControlJobChanged) {
+				notifyControlJobChanged();
 			}
-			else {
-				LOGE("鑾峰彇CC-Link鐘舵�佸け璐�.");
-			}
+
+			LOGI("[BOOT][MASTER] cache/state loaded, cost=%llu ms (since init %llu ms)",
+				(unsigned long long)(GetTickCount64() - boot_cache_begin),
+				(unsigned long long)(GetTickCount64() - boot_master_begin));
+
+
+			// 瀹氭椂鍣�
+			g_pMaster = this;
+			SetTimer(NULL, 1, 250, (TIMERPROC)MasterTimerProc);
+
+
+			// 璋冨害绾跨▼
+			m_hDispatchThreadHandle = (HANDLE)_beginthreadex(NULL, 0, SERVO::DispatchThreadFunction, this,
+				0, &m_nDispatchThreadAddr);
+
+
+			// 鐩戞帶bit绾跨▼
+			m_hReadBitsThreadHandle = (HANDLE)_beginthreadex(NULL, 0, SERVO::ReadBitsThreadFunction, this,
+				0, &m_nReadBitsThreadAddr);
+
+
+			// 鏇茬嚎鏈嶅姟
+			CreateDAQBridgeServer();
+
+
+			LOGI("<Master>鍒濆鍖栧畬鎴�.");
+			LOGI("[BOOT][MASTER] init finished, total cost=%llu ms",
+				(unsigned long long)(GetTickCount64() - boot_master_begin));
+			return 0;
 		}
-
-
-		// 鍒濆鍖栨坊鍔犲悇瀛愯澶�
-		CLoadPort* pPort1, * pPort2, * pPort3, * pPort4;
-		CBonder* pBonder1, * pBonder2;
-		CEFEM* pEfem;
-		CArm* pArm;
-		CArmTray* pArmTray1, * pArmTray2;
-		CFliper* pFliper;
-		CVacuumBake* pVacuumBake;
-		CAligner* pAligner;
-		CBakeCooling* pBakeCooling;
-		CMeasurement* pMeasurement;
-
-		pPort1 = addLoadPort(0);
-		pPort2 = addLoadPort(1);
-		pPort3 = addLoadPort(2);
-		pPort4 = addLoadPort(3);
-		pEfem = addEFEM();
-		pArm = addArm();
-		pArmTray1 = addArmTray(0);
-		pArmTray2 = addArmTray(1);
-		pFliper = addFliper();
-		pVacuumBake = addVacuumBake();
-		pAligner = addAligner();
-		pBonder1 = addBonder(0);
-		pBonder2 = addBonder(1);
-		pBakeCooling = addBakeCooling();
-		pMeasurement = addMeasurement();
-
-		ASSERT(pEfem);
-		ASSERT(pFliper);
-		ASSERT(pVacuumBake);
-		ASSERT(pAligner);
-		ASSERT(pBonder1);
-		ASSERT(pBonder2);
-		ASSERT(pBakeCooling);
-		ASSERT(pMeasurement);
-
-		pEfem->setPort(0, pPort1);
-		pEfem->setPort(1, pPort2);
-		pEfem->setPort(2, pPort3);
-		pEfem->setPort(3, pPort4);
-		pEfem->setFliper(pFliper);
-		pEfem->setAligner(pAligner);
-		pEfem->setArmTray(0, pArmTray1);
-		pEfem->setArmTray(1, pArmTray2);
-		pPort1->setArm(pArm);
-		pPort2->setArm(pArm);
-		pPort3->setArm(pArm);
-		pPort4->setArm(pArm);
-		pArmTray1->setArm(pArm);
-		pArmTray2->setArm(pArm);
-		pFliper->setArm(pArm);
-		pVacuumBake->setArm(pArm);
-		pAligner->setArm(pArm);
-		pBonder1->setArm(pArm);
-		pBonder2->setArm(pArm);
-		pBakeCooling->setArm(pArm);
-		pMeasurement->setArm(pArm);
-
-		connectEquipments();
-
-
-
-		// 璇荤紦瀛樻暟鎹�
-		readCache();
-		loadState();
-		if (m_listener.onControlJobChanged) {
-			m_listener.onControlJobChanged(this);
-		}
-
-
-		// 瀹氭椂鍣�
-		g_pMaster = this;
-		SetTimer(NULL, 1, 250, (TIMERPROC)MasterTimerProc);
-
-
-		// 璋冨害绾跨▼
-		m_hDispatchThreadHandle = (HANDLE)_beginthreadex(NULL, 0, SERVO::DispatchThreadFunction, this,
-			0, &m_nDispatchThreadAddr);
-
-
-		// 鐩戞帶bit绾跨▼
-		m_hReadBitsThreadHandle = (HANDLE)_beginthreadex(NULL, 0, SERVO::ReadBitsThreadFunction, this,
-			0, &m_nReadBitsThreadAddr);
-
-
-		// 鏇茬嚎鏈嶅姟
-		CreateDAQBridgeServer();
-
-
-		LOGI("<Master>鍒濆鍖栧畬鎴�.");
-		return 0;
-	}
 
 	int CMaster::term()
 	{
@@ -878,6 +908,33 @@
 						m_pActiveRobotTask->place();
 					}
 					unlock(); // 绛夊綋鍓嶄换鍔″畬鎴愭垨涓鍚庣户缁�
+					continue;
+				}
+
+				// 5.5) 鏆傚仠鐘舵�佹鏌ワ細鑻� CJ 鎴栧湪鍒� PJ 澶勪簬 Paused锛屾殏缂撹皟搴︽柊鐨勬惉閫�
+				bool pausedByEvent = false;
+				if (m_pControlJob != nullptr && m_pControlJob->state() == CJState::Paused) {
+					pausedByEvent = true;
+				}
+				for (auto pj : m_inProcesJobs) {
+					if (pj != nullptr && pj->state() == PJState::Paused) {
+						pausedByEvent = true;
+						break;
+					}
+				}
+				if (!pausedByEvent && m_bPauseAlarmRaised) {
+					if (m_pModelCtx != nullptr) {
+						m_pModelCtx->clearSoftAlarm(ALID_SOFTWARE_PAUSE_EVENT, 0, 0);
+					}
+					else {
+						AlarmManager& alarmManager = AlarmManager::getInstance();
+						alarmManager.clearAlarmByAttributes(ALID_SOFTWARE_PAUSE_EVENT, 0, 0, CToolUnits::getCurrentTimeString());
+					}
+					m_bPauseAlarmRaised = false;
+				}
+				if (pausedByEvent) {
+					LOGI("<Master>璋冨害鏆傚仠锛欳ontrolJob/ProcessJob 澶勪簬 Paused 鐘舵�侊紙鍙兘鐢� PauseEvent 瑙﹀彂锛�");
+					unlock();
 					continue;
 				}
 
@@ -1637,6 +1694,14 @@
 			}
 		};
 		listener.onSVDataReport = [&](void* pEquipment, void* pData) {
+			const bool allowSvLog =
+				(m_state == MASTERSTATE::RUNNING ||
+					m_state == MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER ||
+					m_state == MASTERSTATE::RUNNING_BATCH ||
+					m_state == MASTERSTATE::STARTING);
+			if (!allowSvLog) {
+				return;
+			}
 			CSVData* pSVData = (CSVData*)pData;
 			auto rawData = pSVData->getSVRawData();
 			std::vector<CParam> params;
@@ -1809,6 +1874,11 @@
 				}
 			}
 
+		};
+		listener.onReceivedJob = [&](void* pEquipment, int port, CJobDataS* pJobDataS) {
+			if (m_listener.onJobReceived != nullptr) {
+				m_listener.onJobReceived(this, (CEquipment*)pEquipment, port, pJobDataS);
+			}
 		};
 		pEquipment->setListener(listener);
 		pEquipment->setCcLink(&m_cclink);
@@ -2209,6 +2279,34 @@
 					fireLoadPortStatus(PORT_LOAD_READY);
 					fireLoadPortStatus(PORT_EMPTY); // will also raise LoadPortNotAssoc via Model
 					break;
+				case 24: { // 妯℃嫙 SV Data锛堢ず渚嬶細Bonder1锛�
+					SERVO::CEquipment* pEq = getEquipment(EQ_ID_Bonder1);
+					if (pEq != nullptr && m_listener.onSVDataReport != nullptr) {
+						static int counter = 0;
+						++counter;
+						std::vector<CParam> params;
+						params.emplace_back("MockSV_Temp", "1", "C", 25 + (counter % 5));
+						params.emplace_back("MockSV_Pressure", "2", "kPa", 100 + (counter % 3));
+						params.emplace_back("MockSV_Speed", "3", "mm/s", 50 + (counter % 7));
+						m_listener.onSVDataReport(this, pEq, params);
+						LOGI("<Master>SIM_EAP step24: mock SVData (Bonder1), params=%zu", params.size());
+					}
+					break;
+				}
+				case 25: { // 妯℃嫙 Process Data锛堢ず渚嬶細Bonder1锛�
+					SERVO::CEquipment* pEq = getEquipment(EQ_ID_Bonder1);
+					if (pEq != nullptr && m_listener.onProcessDataReport != nullptr) {
+						static int counter = 0;
+						++counter;
+						std::vector<CParam> params;
+						params.emplace_back("MockProc_CycleTime", "1", "s", 30 + (counter % 4));
+						params.emplace_back("MockProc_MaxTemp", "2", "C", 200 + (counter % 6));
+						params.emplace_back("MockProc_Result", "3", "", (counter % 2) ? 1 : 0);
+						m_listener.onProcessDataReport(this, pEq, params);
+						LOGI("<Master>SIM_EAP step25: mock ProcessData (Bonder1), params=%zu", params.size());
+					}
+					break;
+				}
 				default:
 					break;
 				}
@@ -2825,7 +2923,7 @@
 
 		this->saveState();
 		if (m_listener.onControlJobChanged) {
-			m_listener.onControlJobChanged(this);
+			notifyControlJobChanged();
 		}
 
 		return (int)m_processJobs.size();
@@ -2885,7 +2983,7 @@
 		m_pControlJob->setPJs(temps);
 		this->saveState();
 		if (m_listener.onControlJobChanged) {
-			m_listener.onControlJobChanged(this);
+			notifyControlJobChanged();
 		}
 
 
@@ -2939,7 +3037,98 @@
 
 	bool CMaster::ceidDefined(uint32_t ceid) const
 	{
-		return true;
+		if (m_allowedCeids.empty()) return true; // backward compatible: treat as all allowed when not configured
+		return m_allowedCeids.find(ceid) != m_allowedCeids.end();
+	}
+
+	bool CMaster::raiseSoftAlarm(int alarmId,
+		const std::string& desc,
+		int level/* = -1*/,
+		int deviceId/* = 0*/,
+		int unitId/* = 0*/,
+		const char* deviceName/* = "Software"*/,
+		const char* unitName/* = "App"*/)
+	{
+		AlarmManager& alarmManager = AlarmManager::getInstance();
+		const AlarmInfo* info = alarmManager.getAlarmInfoByID(alarmId);
+
+		int severity = level;
+		if (severity < 0 && info != nullptr) {
+			severity = info->nAlarmLevel;
+		}
+		if (severity < 0) severity = 0; // fallback
+
+		std::string descText = desc;
+		if (descText.empty() && info != nullptr) {
+			descText = !info->strDescription.empty() ? info->strDescription : info->strAlarmText;
+		}
+		if (descText.empty()) {
+			descText = CToolUnits::formatString("Alarm %d", alarmId);
+		}
+
+		AlarmData alarmData;
+		alarmData.nId = alarmId;
+		alarmData.nSeverityLevel = severity;
+		alarmData.nDeviceId = deviceId;
+		alarmData.nUnitId = unitId;
+		alarmData.strDeviceName = deviceName;
+		alarmData.strUnitName = unitName;
+		alarmData.strStartTime = CToolUnits::timeToString2(CToolUnits::getTimestamp());
+		alarmData.strEndTime = "";
+		alarmData.strDescription = descText;
+
+		int nAlarmEventId = 0;
+		return alarmManager.addAlarm(alarmData, nAlarmEventId);
+	}
+
+	void CMaster::handleCollectionEvent(uint32_t ceid)
+	{
+		// 閬嶅巻褰撳墠 PJ锛屽懡涓� pauseEvents 鏃跺彲鍦ㄦ鎵╁睍鏆傚仠鍔ㄤ綔
+		bool pausedAny = false;
+		for (auto pj : m_processJobs) {
+			if (pj == nullptr) continue;
+			const auto& pauseList = pj->pauseEvents();
+			if (std::find(pauseList.begin(), pauseList.end(), ceid) != pauseList.end()) {
+				LOGW("<Master>PauseEvent hit: CEID=%u, PJ=%s, state=%d", ceid, pj->id().c_str(), (int)pj->state());
+				if (pj->pause()) {
+					LOGI("<Master>PJ paused by CEID=%u", ceid);
+					pausedAny = true;
+				}
+				if (m_pControlJob != nullptr && m_pControlJob->state() == CJState::Executing) {
+					if (m_pControlJob->pause()) {
+						LOGI("<Master>ControlJob paused by CEID=%u", ceid);
+						pausedAny = true;
+					}
+				}
+			}
+		}
+		if (pausedAny && m_listener.onControlJobChanged) {
+			// 閫氱煡搴旂敤灞傚埛鏂� UI/鎸夐挳鐘舵��
+			notifyControlJobChanged();
+		}
+		if (pausedAny && !m_bPauseAlarmRaised) {
+			std::string desc = CToolUnits::formatString("<PauseEvent CEID=%u>", ceid);
+			bool raised = false;
+			if (m_pModelCtx != nullptr) {
+				raised = m_pModelCtx->raiseSoftAlarm(ALID_SOFTWARE_PAUSE_EVENT, desc);
+			}
+			else {
+				raised = raiseSoftAlarm(ALID_SOFTWARE_PAUSE_EVENT, desc);
+			}
+			if (raised) {
+				LOGI("<Master>PauseEvent soft alarm raised, CEID=%u", ceid);
+				m_bPauseAlarmRaised = true;
+			}
+		}
+	}
+
+	void CMaster::setAllowedCeids(const std::vector<unsigned int>& ceids)
+	{
+		m_allowedCeids.clear();
+		m_allowedCeids.reserve(ceids.size());
+		for (auto id : ceids) {
+			m_allowedCeids.insert(id);
+		}
 	}
 
 	bool CMaster::saveState() const
@@ -3230,7 +3419,7 @@
 
 		saveState();
 		if (m_listener.onControlJobChanged) {
-			m_listener.onControlJobChanged(this);
+			notifyControlJobChanged();
 		}
 
 		return true;
@@ -3267,7 +3456,7 @@
 
 		saveState();
 		if (m_listener.onControlJobChanged) {
-			m_listener.onControlJobChanged(this);
+			notifyControlJobChanged();
 		}
 
 		return true;

--
Gitblit v1.9.3