From e9c66dce803984d9eb0c026df8f50ad196fd0650 Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期二, 22 七月 2025 16:20:25 +0800
Subject: [PATCH] 1.将原来的设置CassetteType更新到EFEM的功能,修改为本地保存,因为EFEM不需要这些数据; 2.配置是否需要比较map的一致性; 3.收到EFEM的PortStarus,INUSE状态时,弹出配置对话框;打勾选择要加工的产品;

---
 SourceCode/Bond/Servo/CPageGraph2.cpp          |   25 ---
 SourceCode/Bond/Servo/CPagePortProperty.cpp    |    8 +
 SourceCode/Bond/Servo/CGlass.cpp               |   13 +
 SourceCode/Bond/Servo/CGlass.h                 |    3 
 SourceCode/Bond/Servo/CLoadPort.h              |    8 +
 SourceCode/Bond/Servo/Configuration.cpp        |   15 ++
 SourceCode/Bond/Servo/CMaster.h                |    7 +
 SourceCode/Bond/Servo/Model.cpp                |   12 +
 SourceCode/Bond/Servo/CLoadPort.cpp            |  108 ++++++++++++--
 SourceCode/Bond/Servo/PortConfigurationDlg.h   |    6 
 SourceCode/Bond/Servo/ServoDlg.cpp             |    8 +
 SourceCode/Bond/Servo/CPortStatusReport.cpp    |   12 +
 SourceCode/Bond/Servo/Configuration.h          |    2 
 SourceCode/Bond/Servo/PortConfigurationDlg.cpp |  108 ++++++---------
 SourceCode/Bond/Servo/CEquipment.cpp           |    2 
 SourceCode/Bond/Servo/CPortStatusReport.h      |    2 
 SourceCode/Bond/Servo/Model.h                  |    1 
 SourceCode/Bond/Servo/Servo.rc                 |    0 
 SourceCode/Bond/Servo/CMaster.cpp              |   21 +++
 SourceCode/Bond/Servo/CEquipment.h             |    3 
 SourceCode/Bond/Servo/Common.h                 |    1 
 21 files changed, 256 insertions(+), 109 deletions(-)

diff --git a/SourceCode/Bond/Servo/CEquipment.cpp b/SourceCode/Bond/Servo/CEquipment.cpp
index fce26d2..0d99db6 100644
--- a/SourceCode/Bond/Servo/CEquipment.cpp
+++ b/SourceCode/Bond/Servo/CEquipment.cpp
@@ -1318,6 +1318,7 @@
 			CGlass* pGlass = (CGlass*)m_slot[i].getContext();
 			if (!isSlotProcessed(i)) continue;
 			if (pGlass == nullptr) continue;
+			if (!pGlass->isScheduledForProcessing()) continue;
 			if(pGlass->getInspResult(m_nID, 0) == InspResult::Fail) continue;
 			int lsPath = m_slot[i].getLinkSignalPath();
 			if(!m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_INLINE]
@@ -1370,6 +1371,7 @@
 			if (m_slot[i].isLock()) continue;
 			CGlass* pGlass = (CGlass*)m_slot[i].getContext();
 			if (pGlass == nullptr) continue;
+			if (!pGlass->isScheduledForProcessing()) continue;
 			if (pGlass->getInspResult(m_nID, 0) != InspResult::Fail) continue;
 			int lsPath = m_slot[i].getLinkSignalPath();
 			if (!m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_INLINE]
diff --git a/SourceCode/Bond/Servo/CEquipment.h b/SourceCode/Bond/Servo/CEquipment.h
index 1a35b85..079e4af 100644
--- a/SourceCode/Bond/Servo/CEquipment.h
+++ b/SourceCode/Bond/Servo/CEquipment.h
@@ -55,6 +55,7 @@
 	typedef std::function<BOOL(void* pEiuipment, int port, CJobDataB* pJobDataB, short& putSlot)> ONPRESTOREDJOB;
 	typedef std::function<void(void* pEiuipment, PROCESS_STATE state)> ONPROCESSSTATE;
 	typedef std::function<void(void* pEiuipment, short scanMap, short downMap)> ONMAPMISMATCH;
+	typedef std::function<void(void* pEiuipment, short scanMap)> ONPORTINUSE;
 	typedef struct _EquipmentListener
 	{
 		ONALIVE				onAlive;
@@ -66,6 +67,8 @@
 		ONPRESTOREDJOB		onPreStoredJob;
 		ONPROCESSSTATE		onProcessStateChanged;
 		ONMAPMISMATCH		onMapMismatch;
+		ONPORTINUSE			onPortInUse;
+
 	} EquipmentListener;
 
 
diff --git a/SourceCode/Bond/Servo/CGlass.cpp b/SourceCode/Bond/Servo/CGlass.cpp
index 6d1a1ee..6c1b30f 100644
--- a/SourceCode/Bond/Servo/CGlass.cpp
+++ b/SourceCode/Bond/Servo/CGlass.cpp
@@ -10,6 +10,7 @@
 		m_pBuddy = nullptr;
 		m_nOriginPort = 0;
 		m_nOriginSlot = 0;
+		m_bScheduledForProcessing = FALSE;
 	}
 
 	CGlass::~CGlass()
@@ -80,6 +81,16 @@
 		slot = m_nOriginSlot;
 	}
 
+	BOOL CGlass::isScheduledForProcessing()
+	{
+		return m_bScheduledForProcessing;
+	}
+	
+	void CGlass::setScheduledForProcessing(BOOL bProcessing)
+	{
+		m_bScheduledForProcessing = bProcessing;
+	}
+
 	CPath* CGlass::getPath()
 	{
 		return m_pPath;
@@ -119,6 +130,7 @@
 			WriteString(ar, m_strID);
 			ar << m_nOriginPort;
 			ar << m_nOriginSlot;
+			ar << m_bScheduledForProcessing;
 			ar << (ULONGLONG)m_pPath;
 			if (m_pPath != nullptr) {
 				m_pPath->serialize(ar);
@@ -141,6 +153,7 @@
 			ReadString(ar, m_strID);
 			ar >> m_nOriginPort;
 			ar >> m_nOriginSlot;
+			ar >> m_bScheduledForProcessing;
 			ar >> ullPath;
 			if (ullPath != 0) {
 				m_pPath = new CPath();
diff --git a/SourceCode/Bond/Servo/CGlass.h b/SourceCode/Bond/Servo/CGlass.h
index 3127839..844822b 100644
--- a/SourceCode/Bond/Servo/CGlass.h
+++ b/SourceCode/Bond/Servo/CGlass.h
@@ -26,6 +26,8 @@
 		std::string& getID();
 		void setOriginPort(int port, int slot);
 		void getOrginPort(int& port, int& slot);
+		BOOL isScheduledForProcessing();
+		void setScheduledForProcessing(BOOL bProcessing);
 		CPath* getPathWithEq(unsigned int nEqId, unsigned int nUnit);
 		CPath* getPath();
 		void addPath(unsigned int nEqId, unsigned int nUnit);
@@ -51,6 +53,7 @@
 		std::string m_strBuddyId;
 		int m_nOriginPort;
 		int m_nOriginSlot;
+		BOOL m_bScheduledForProcessing;			/* 是否将加工处理 */
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CLoadPort.cpp b/SourceCode/Bond/Servo/CLoadPort.cpp
index b5d4af4..5de17db 100644
--- a/SourceCode/Bond/Servo/CLoadPort.cpp
+++ b/SourceCode/Bond/Servo/CLoadPort.cpp
@@ -16,6 +16,7 @@
 		m_bEnable = FALSE;
 		m_bAutoChangeEnable = FALSE;
 		m_nNextCassetteSequenceNo = 0;
+		m_isCompareMapsBeforeProceeding = FALSE;
 	}
 
 	CLoadPort::~CLoadPort()
@@ -134,7 +135,7 @@
 			CEqReadStep* pStep = new CEqReadStep(dev[m_nIndex], sizeof(short),
 				[&](void* pFrom, int code, const char* pszData, size_t size) -> int {
 					if (code == ROK && pszData != nullptr && size > 0) {
-						m_cassetteType = (CassetteType)CToolUnits::toInt16(pszData);
+						//m_cassetteType = (CassetteType)CToolUnits::toInt16(pszData);
 					}
 					return 0;
 				});
@@ -347,6 +348,21 @@
 	void CLoadPort::onTimer(UINT nTimerid)
 	{
 		CEquipment::onTimer(nTimerid);
+
+		// 模拟测试
+		if (m_nIndex == 0) {
+			static int ii = 0;
+			ii++;
+			if (ii == 50) {
+				char szBuffer[64];
+				CStep* pStep = getStepWithName(STEP_EQ_PORT1_INUSE);
+				CPortStatusReport portStatusReport;
+				portStatusReport.setPortStatus(PORT_INUSE);
+				portStatusReport.setJobExistenceSlot(0xf);
+				int nRet = portStatusReport.serialize(szBuffer, 64);
+				decodePortStatusReport(pStep, szBuffer, 64);
+			}
+		}
 	}
 
 	void CLoadPort::serialize(CArchive& ar)
@@ -887,17 +903,27 @@
 
 		// 当port状态为InUse, 比较map
 		if (m_portStatusReport.getPortStatus() == PORT_INUSE) {
-			short scanMap = m_portStatusReport.getJobExistenceSlot();
-			short downMap = getCassetteMap();
-			if (scanMap == downMap) {
-				this->sendCassetteCtrlCmd(CCC_PROCESS_START, nullptr, 0, 0, 0, nullptr, nullptr);
+			if (m_isCompareMapsBeforeProceeding) {
+				short scanMap = getScanCassetteMap();
+				short downloadMap = getDownloadCassetteMap();
+				if (scanMap == downloadMap) {
+					generateGlassList(scanMap);
+					this->sendCassetteCtrlCmd(CCC_PROCESS_START, nullptr, 0, 0, 0, nullptr, nullptr);
+				}
+				else {
+					this->sendCassetteCtrlCmd(CCC_PROCESS_CANCEL, nullptr, 0, 0, 0, nullptr, nullptr);
+
+					// 抛出到应用层做提示
+					if (m_listener.onMapMismatch != nullptr) {
+						m_listener.onMapMismatch(this, scanMap, downloadMap);
+					}
+				}
 			}
 			else {
-				this->sendCassetteCtrlCmd(CCC_PROCESS_CANCEL, nullptr, 0, 0, 0, nullptr, nullptr);
-
-				// 抛出到应用层做提示
-				if (m_listener.onMapMismatch != nullptr) {
-					m_listener.onMapMismatch(this, scanMap, downMap);
+				// 抛出到应用层做选择要加工的片子
+				generateGlassList(getScanCassetteMap());
+				if (m_listener.onPortInUse != nullptr) {
+					m_listener.onPortInUse(this, getScanCassetteMap());
 				}
 			}
 		}
@@ -1011,6 +1037,7 @@
 
 	int CLoadPort::setCassetteType(CassetteType type, ONWRITED onWritedBlock/* = nullptr*/)
 	{
+		m_cassetteType = type;
 		static char* pszName[] = { STEP_PORT1_CASSETTE_TYPE_CHANGE, STEP_PORT2_CASSETTE_TYPE_CHANGE, STEP_PORT3_CASSETTE_TYPE_CHANGE, STEP_PORT4_CASSETTE_TYPE_CHANGE };
 		SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(pszName[m_nIndex]);
 		if (pStep == nullptr) {
@@ -1023,7 +1050,6 @@
 			// test
 			code = WOK;
 			if (code == WOK) {
-				m_cassetteType = type;
 				LOGI("<CLoadPort-%d>设置Cassette Type成功.", m_nIndex);
 			}
 			else {
@@ -1126,15 +1152,15 @@
 		m_bAutoChangeEnable = bEnable;
 	}
 
-	short CLoadPort::getCassetteMap()
+	short CLoadPort::getScanCassetteMap()
 	{
-		short map = 0;
-		for (int i = 0; i < SLOT_MAX; i++) {
-			if (!m_slot[i].isEnable()) continue;
-			if (m_slot[i].getContext() == nullptr) continue;
-			map |= (1 << i);
-		}
+		return m_portStatusReport.getJobExistenceSlot();
+	}
 
+	short CLoadPort::getDownloadCassetteMap()
+	{
+		// 暂时未实现此功能
+		short map = 0;
 		return map;
 	}
 
@@ -1176,6 +1202,47 @@
 		return 0;
 	}
 
+	/*
+	 * 根据efem扫描到的map,生成玻璃列表
+	 */
+	int CLoadPort::generateGlassList(short map)
+	{
+		// 先释放较早前的数据
+		Lock();
+		for (int i = 0; i < SLOT_MAX; i++) {
+			m_slot[i].setContext(nullptr);
+		}
+		Unlock();
+
+
+		// 根据map生成新的
+		char szBuffer[64];
+		for (int i = 0; i < SLOT_MAX; i++) {
+			if (!m_slot[i].isEnable()) continue;
+			if (!(map >> i) & 1) continue;
+
+			CJobDataS js;
+			js.setCassetteSequenceNo(getNextCassetteSequenceNo());
+			js.setJobSequenceNo(m_slot[i].getNo());
+			sprintf_s(szBuffer, 64, "%05d%05d", js.getCassetteSequenceNo(), js.getJobSequenceNo());
+			js.setJobType(1);
+			js.setMaterialsType((int)m_cassetteType);
+
+			CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass();
+			pGlass->setOriginPort(m_nIndex, i);
+			pGlass->setScheduledForProcessing(i % 2 == 1);
+			pGlass->addPath(m_nID, 0);
+			pGlass->processEnd(m_nID, 0);
+			pGlass->setID(szBuffer);
+			pGlass->setType(m_cassetteType);
+			pGlass->setJobDataS(&js);
+			m_slot[i].setContext(pGlass);
+		}
+
+		return 0;
+	}
+
+
 	int CLoadPort::testGenerateGlassListFromConfig(const SERVO::PortConfig& config)
 	{
 		char szBuffer[64];
@@ -1215,4 +1282,9 @@
 
 		return 0;
 	}
+
+	void CLoadPort::setCompareMapsBeforeProceeding(BOOL bCompare)
+	{
+		m_isCompareMapsBeforeProceeding = bCompare;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CLoadPort.h b/SourceCode/Bond/Servo/CLoadPort.h
index b8279c2..12776df 100644
--- a/SourceCode/Bond/Servo/CLoadPort.h
+++ b/SourceCode/Bond/Servo/CLoadPort.h
@@ -37,7 +37,8 @@
 		void localSetCessetteType(CassetteType type);
 		void localSetTransferMode(TransferMode mode);
 		void localAutoChangeEnable(BOOL bEnable);
-		short getCassetteMap();
+		short getScanCassetteMap();
+		short getDownloadCassetteMap();
 
 	public:
 		short getNextCassetteSequenceNo();
@@ -57,6 +58,7 @@
 		int getCassetteMappingState();
 		int getCassetteStatus();
 		int testGenerateGlassList(MaterialsType type);
+		int generateGlassList(short map);
 		int testGenerateGlassListFromConfig(const SERVO::PortConfig& config);
 
 	public:
@@ -80,6 +82,7 @@
 			CJobDataA* pJobDataA,
 			ONWRITED onWritedBlock);
 		CStep* getCassetteCtrlCmdStep();
+		void setCompareMapsBeforeProceeding(BOOL bCompare);
 
 	private:
 		int decodePortStatusReport(CStep* pStep, const char* pszData, size_t size);
@@ -94,6 +97,9 @@
 		BOOL m_bAutoChangeEnable;
 		CPortStatusReport m_portStatusReport;
 		int m_nNextCassetteSequenceNo;
+
+		// 在开始工艺前是否先需要先比较map
+		BOOL m_isCompareMapsBeforeProceeding;
 	};
 }
 
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index efe5e91..3756560 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -51,6 +51,7 @@
 		m_state = MASTERSTATE::READY;
 		m_pActiveRobotTask = nullptr;
 		m_nLastError = 0;
+		m_isCompareMapsBeforeProceeding = FALSE;
 		InitializeCriticalSection(&m_criticalSection);
 	}
 
@@ -1016,6 +1017,12 @@
 			LOGE("<Master-%s>Port InUse, map(%d!=%d)不一致,请检查。",
 				((CEquipment*)pEquipment)->getName().c_str(), scanMap, downMap);
 		};
+		listener.onPortInUse = [&](void* pEquipment, short scanMap) {
+			LOGE("<Master-%s>Port InUse。scanMap=%d", ((CEquipment*)pEquipment)->getName().c_str(), scanMap);
+			if (m_listener.onLoadPortInUse != nullptr) {
+				m_listener.onLoadPortInUse(this, (CEquipment*)pEquipment, scanMap);
+			}
+		};
 		pEquipment->setListener(listener);
 		pEquipment->setCcLink(&m_cclink);
 		m_listEquipment.push_back(pEquipment);
@@ -1053,6 +1060,7 @@
 		pEquipment->setID(EQ_ID_LOADPORT1 + index);
 		pEquipment->setName(szName);
 		pEquipment->setDescription(szName);
+		pEquipment->setCompareMapsBeforeProceeding(m_isCompareMapsBeforeProceeding);		
 		addToEquipmentList(pEquipment);
 
 
@@ -1609,4 +1617,17 @@
 		pPort->localSetTransferMode((SERVO::TransferMode)transferMode);
 		pPort->localAutoChangeEnable(autoChangeEnable);
 	}
+
+	void CMaster::setPortCassetteType(unsigned int index, SERVO::CassetteType type)
+	{
+		ASSERT(index < 4);
+		int eqid[] = { EQ_ID_LOADPORT1, EQ_ID_LOADPORT2, EQ_ID_LOADPORT3, EQ_ID_LOADPORT4 };
+		CLoadPort* pPort = (CLoadPort*)getEquipment(eqid[index]);
+		pPort->localSetCessetteType(type);
+	}
+
+	void CMaster::setCompareMapsBeforeProceeding(BOOL bCompare)
+	{
+		m_isCompareMapsBeforeProceeding = bCompare;
+	}
 }
diff --git a/SourceCode/Bond/Servo/CMaster.h b/SourceCode/Bond/Servo/CMaster.h
index 786f644..57756d0 100644
--- a/SourceCode/Bond/Servo/CMaster.h
+++ b/SourceCode/Bond/Servo/CMaster.h
@@ -31,6 +31,7 @@
     typedef std::function<void(void* pMaster, CEquipment* pEquipment, CVcrEventReport* pReport)> ONEQVCREVENTREPORT;
     typedef std::function<void(void* pMaster, CEquipment* pEquipment, int code)> ONEQDATACHANGED;
     typedef std::function<void(void* pMaster, CRobotTask* pTask, int code)> ONROBOTTASKEVENT;
+    typedef std::function<void(void* pMaster, CEquipment* pEquipment, short scanMap)> ONLOADPORTINUSE;
     typedef struct _MasterListener
     {
         ONMASTERSTATECHANGED    onMasterStateChanged;
@@ -40,6 +41,7 @@
         ONEQVCREVENTREPORT	    onEqVcrEventReport;
         ONEQDATACHANGED         onEqDataChanged;
         ONROBOTTASKEVENT        onRobotTaskEvent;
+        ONLOADPORTINUSE			onLoadPortInUse;
     } MasterListener;
 
     class CMaster
@@ -70,6 +72,8 @@
         int resendCurrentTask();
         void setPortType(unsigned int index, BOOL enable, int type, int mode,
             int cassetteType, int transferMode, BOOL autoChangeEnable);
+        void setPortCassetteType(unsigned int index, SERVO::CassetteType type);
+        void setCompareMapsBeforeProceeding(BOOL bCompare);
 
     private:
         inline void lock() { EnterCriticalSection(&m_criticalSection); }
@@ -131,6 +135,9 @@
         // 错误代码
         int m_nLastError;
         std::string m_strLastError;
+
+        // 在开始工艺前是否先需要先比较map
+        BOOL m_isCompareMapsBeforeProceeding;
     };
 }
 
diff --git a/SourceCode/Bond/Servo/CPageGraph2.cpp b/SourceCode/Bond/Servo/CPageGraph2.cpp
index 3db47cb..eca3e9e 100644
--- a/SourceCode/Bond/Servo/CPageGraph2.cpp
+++ b/SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -212,30 +212,7 @@
 
 		// 娴嬭瘯
 		else if (nCmd == ID_EQSGRAPHITEM_TEST1) {
-			BOOL bTestGenerate = FALSE;
-			SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
-			if (pEquipment->getID() == EQ_ID_LOADPORT4 && !pEquipment->hasGlass()) {
-				((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G1);
-				bTestGenerate = TRUE;
-			}
-			/*
-			else if (pEquipment->getID() == EQ_ID_LOADPORT1 && !pEquipment->hasGlass()) {
-				((SERVO::CLoadPort*)pEquipment)->testGenerateGlassList(SERVO::MaterialsType::G2);
-				bTestGenerate = TRUE;
-			}
-			*/
-			if (!bTestGenerate) {
-				SERVO::CRobotTask* pTask = theApp.m_model.getMaster().getActiveRobotTask();
-				if (pTask != nullptr) {
-					SERVO::CGlass* pGlass = (SERVO::CGlass*)pTask->getContext();
-					SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS();
-					if (pJobDataS != nullptr) {
-						SERVO::CJobDataB jobDataB;
-						pEquipment->onFetchedOutJob(0, &pJobDataS->getJobDataB(jobDataB));
-						pEquipment->onSentOutJob(0, pJobDataS);
-					}
-				}
-			}
+
 		}
 		else if (nCmd == ID_EQSGRAPHITEM_TEST2) {
 			SERVO::CEquipment* pEquipment = (SERVO::CEquipment*)pItem->pData;
diff --git a/SourceCode/Bond/Servo/CPagePortProperty.cpp b/SourceCode/Bond/Servo/CPagePortProperty.cpp
index 380e35d..492a2a7 100644
--- a/SourceCode/Bond/Servo/CPagePortProperty.cpp
+++ b/SourceCode/Bond/Servo/CPagePortProperty.cpp
@@ -280,6 +280,13 @@
 
 void CPagePortProperty::OnCbnSelchangeComboPortCassertType()
 {
+	// 鐢卞師鏉ョ殑鏇存柊鍒癊FEM, 淇敼涓轰繚瀛樺埌鏈湴ini鏂囦欢
+	ASSERT(m_pPort != nullptr);
+	int index = ((CComboBox*)GetDlgItem(IDC_COMBO_PORT_CASSERT_TYPE))->GetCurSel();
+	theApp.m_model.setPortCassetteType(m_pPort->getIndex(), SERVO::CassetteType(index + 1));
+
+
+	/*
 	g_nMsgDlgShow = 0;
 	CMsgDlg msgDlg("璇风瓑寰�", "姝e湪鎿嶄綔锛岃绛夊緟...");
 	msgDlg.SetData((DWORD_PTR)this);
@@ -322,6 +329,7 @@
 
 	msgDlg.DoModal();
 	g_nMsgDlgShow = 1;
+	*/
 }
 
 void CPagePortProperty::OnCbnSelchangeComboPortTransferMode()
diff --git a/SourceCode/Bond/Servo/CPortStatusReport.cpp b/SourceCode/Bond/Servo/CPortStatusReport.cpp
index e132f12..0a0453d 100644
--- a/SourceCode/Bond/Servo/CPortStatusReport.cpp
+++ b/SourceCode/Bond/Servo/CPortStatusReport.cpp
@@ -51,6 +51,11 @@
 		return m_nPortStatus;
 	}
 
+	void CPortStatusReport::setPortStatus(short status)
+	{
+		m_nPortStatus = status;
+	}
+
 	short CPortStatusReport::getCassetteSequenceNo()
 	{
 		return m_nCassetteSequenceNo;
@@ -146,7 +151,7 @@
 		memcpy(&m_nCassetteStatus, &pszBuffer[index], sizeof(short));
 		index += sizeof(short);
 
-		return 15 * 2;
+		return 32 * 2;
 	}
 
 	void CPortStatusReport::getAttributeVector(CAttributeVector& attrubutes, int beginWeight)
@@ -242,6 +247,11 @@
 		return m_nJobExistenceSlot[0];
 	}
 
+	void CPortStatusReport::setJobExistenceSlot(short map)
+	{
+		m_nJobExistenceSlot[0] = map;
+	}
+
 	void CPortStatusReport::WriteString(CArchive& ar, std::string& string)
 	{
 		CString strTemp = string.c_str();
diff --git a/SourceCode/Bond/Servo/CPortStatusReport.h b/SourceCode/Bond/Servo/CPortStatusReport.h
index 0555d51..727a7d9 100644
--- a/SourceCode/Bond/Servo/CPortStatusReport.h
+++ b/SourceCode/Bond/Servo/CPortStatusReport.h
@@ -14,6 +14,7 @@
 	public:
 		void copyEx(CPortStatusReport& other);
 		short getPortStatus();
+		void setPortStatus(short status);
 		short getCassetteSequenceNo();
 		std::string& getCassetteId();
 		short getLoadingCassetteType();
@@ -29,6 +30,7 @@
 		bool canPickFromPort();
 		bool isJobExistenceSlot();
 		short getJobExistenceSlot();
+		void setJobExistenceSlot(short map);
 
 	private:
 		void WriteString(CArchive& ar, std::string& string);
diff --git a/SourceCode/Bond/Servo/Common.h b/SourceCode/Bond/Servo/Common.h
index cc58f4f..7923773 100644
--- a/SourceCode/Bond/Servo/Common.h
+++ b/SourceCode/Bond/Servo/Common.h
@@ -18,6 +18,7 @@
 #define RX_CODE_EQ_DATA_CHANGED			1010
 #define RX_CODE_MASTER_STATE_CHANGED	1011
 #define RX_CODE_EQ_ROBOT_TASK			1012
+#define RX_CODE_LOADPORT_INUSE			1013
 
 
 /* Channel Name */
diff --git a/SourceCode/Bond/Servo/Configuration.cpp b/SourceCode/Bond/Servo/Configuration.cpp
index 5df0f4b..6402828 100644
--- a/SourceCode/Bond/Servo/Configuration.cpp
+++ b/SourceCode/Bond/Servo/Configuration.cpp
@@ -136,3 +136,18 @@
 	return TRUE;
 }
 
+BOOL CConfiguration::setPortCassetteType(unsigned int index, int cassetteType)
+{
+	if (index >= 4) return FALSE;
+	if (cassetteType < 1 || 3 < cassetteType) return FALSE;
+
+	static char* pszSection[] = { "Port1", "Port2", "Port3", "Port4" };
+	WritePrivateProfileString(pszSection[index], _T("CassetteType"), std::to_string(cassetteType).c_str(), m_strFilepath);
+	return true;
+}
+
+BOOL CConfiguration::isCompareMapsBeforeProceeding()
+{
+	return GetPrivateProfileInt(_T("Master"), _T("CompareMapsBeforeProceeding"), 0, m_strFilepath);
+}
+
diff --git a/SourceCode/Bond/Servo/Configuration.h b/SourceCode/Bond/Servo/Configuration.h
index 1de8b08..036e811 100644
--- a/SourceCode/Bond/Servo/Configuration.h
+++ b/SourceCode/Bond/Servo/Configuration.h
@@ -24,6 +24,8 @@
 	int getFilterMode();
 	BOOL getPortParms(unsigned int index, BOOL& bEnable, int& type, int& mode,
 		int& cassetteType, int& transferMode, BOOL& bAutoChangeEnable);
+	BOOL setPortCassetteType(unsigned int index, int cassetteType);
+	BOOL isCompareMapsBeforeProceeding();
 
 public:
 	void setP2RemoteEqReconnectInterval(int second);
diff --git a/SourceCode/Bond/Servo/Model.cpp b/SourceCode/Bond/Servo/Model.cpp
index 6c36c56..7f3ed76 100644
--- a/SourceCode/Bond/Servo/Model.cpp
+++ b/SourceCode/Bond/Servo/Model.cpp
@@ -52,6 +52,12 @@
 	}
 }
 
+void CModel::setPortCassetteType(unsigned int index, SERVO::CassetteType type)
+{
+	m_master.setPortCassetteType(index, type);
+	m_configuration.setPortCassetteType(index, (int)type);
+}
+
 int CModel::init()
 {
 	CString strIniFile;
@@ -274,6 +280,10 @@
 		notifyPtrAndInt(RX_CODE_EQ_ROBOT_TASK, pTask, nullptr, code);
 
 	};
+	masterListener.onLoadPortInUse = [&] (void* pMaster, SERVO::CEquipment* pEquipment, short scanMap) {
+		LOGE("<CModel>onLoadPortInUse. scanMap = %d", scanMap);
+		notifyPtr(RX_CODE_LOADPORT_INUSE, pEquipment);
+	};
 	m_master.setListener(masterListener);
 
 
@@ -281,7 +291,7 @@
 	CString strMasterDataFile;
 	strMasterDataFile.Format(_T("%s\\Master.dat"), (LPTSTR)(LPCTSTR)m_strWorkDir);
 	m_master.setCacheFilepath((LPTSTR)(LPCTSTR)strMasterDataFile);
-
+	m_master.setCompareMapsBeforeProceeding(m_configuration.isCompareMapsBeforeProceeding());
 
 	// 加载警告信息
 	AlarmManager& alarmManager = AlarmManager::getInstance();
diff --git a/SourceCode/Bond/Servo/Model.h b/SourceCode/Bond/Servo/Model.h
index d2c4e0c..0679568 100644
--- a/SourceCode/Bond/Servo/Model.h
+++ b/SourceCode/Bond/Servo/Model.h
@@ -15,6 +15,7 @@
 	SERVO::CMaster& getMaster();
 	void setWorkDir(const char* pszWorkDir);
 	void loadPortParams();
+	void setPortCassetteType(unsigned int index, SERVO::CassetteType type);
 	int init();
 	int term();
 
diff --git a/SourceCode/Bond/Servo/PortConfigurationDlg.cpp b/SourceCode/Bond/Servo/PortConfigurationDlg.cpp
index b941707..891aaac 100644
--- a/SourceCode/Bond/Servo/PortConfigurationDlg.cpp
+++ b/SourceCode/Bond/Servo/PortConfigurationDlg.cpp
@@ -24,10 +24,16 @@
     m_pPort[1] = dynamic_cast<SERVO::CLoadPort*>(theApp.m_model.m_master.getEquipment(EQ_ID_LOADPORT2));
     m_pPort[2] = dynamic_cast<SERVO::CLoadPort*>(theApp.m_model.m_master.getEquipment(EQ_ID_LOADPORT3));
     m_pPort[3] = dynamic_cast<SERVO::CLoadPort*>(theApp.m_model.m_master.getEquipment(EQ_ID_LOADPORT4));
+    m_nCurSelPort = -1;
 }
 
 CPortConfigurationDlg::~CPortConfigurationDlg()
 {
+}
+
+void CPortConfigurationDlg::setCurSelPort(int sel)
+{
+    m_nCurSelPort = sel;
 }
 
 int CPortConfigurationDlg::GetLoadPortEqID(const std::string& strPortName)
@@ -57,19 +63,21 @@
             continue;
         }
 
-        SERVO::CGlass* pGlass = dynamic_cast<SERVO::CGlass*>(pSlot->getContext());
-        int nRow = i + 1;
 
         // 璁剧疆 Panel ID 鍜屽嬀閫夋
-        CGridCellCheck* pCheck = static_cast<CGridCellCheck*>(m_wndGrid.GetCell(nRow, 1));
-        if (pCheck && pGlass) {
-            pCheck->SetCheck(pSlot->isEnable() ? TRUE : FALSE);
-            pCheck->SetText(pGlass ? pGlass->getID().c_str() : _T(""));
+        SERVO::CGlass* pGlass = dynamic_cast<SERVO::CGlass*>(pSlot->getContext());
+        int nRow = i + 1;
+        if (pGlass != nullptr) {
+            m_wndGrid.SetItemState(nRow, 0, GVIS_READONLY);
+            m_wndGrid.SetItemText(nRow, 0, pSlot->getName().c_str());
+            m_wndGrid.SetCellType(nRow, 1, RUNTIME_CLASS(CGridCellCheck));
+            CGridCellCheck* pCheck = dynamic_cast<CGridCellCheck*>(m_wndGrid.GetCell(nRow, 1));
+            ASSERT(pCheck);
+            pCheck->SetCheck(pGlass->isScheduledForProcessing());
+            pCheck->SetText(pGlass->getID().c_str());
         }
-		else {
-			pCheck->SetCheck(FALSE);
-			pCheck->SetText(_T(""));
-		}
+        m_wndGrid.SetItemData(nRow, 0, (LPARAM)pGlass);
+
 
         // 鍥炲~ Job 淇℃伅锛堝彧鍙栫涓�涓湁鏁� Glass锛�
         if (!bJobInfoSet && pGlass) {
@@ -138,33 +146,6 @@
     for (int i = 0; i < nRows; ++i) {
         m_wndGrid.SetRowHeight(i, nEachRowHeight);
     }
-
-    FillGrid();
-}
-
-void CPortConfigurationDlg::FillGrid()
-{
-    //CStringArray recipeOptions;
-    //recipeOptions.Add(_T("Recipe A"));
-    //recipeOptions.Add(_T("Recipe B"));
-    //recipeOptions.Add(_T("Recipe C"));
-
-    for (int i = 1; i < 9; ++i) {
-        CString strIndex;
-        strIndex.Format(_T("%d"), i);
-        m_wndGrid.SetItemText(i, 0, strIndex);
-        m_wndGrid.SetItemState(i, 0, GVIS_READONLY);
-
-        // Checkbox
-        m_wndGrid.SetCellType(i, 1, RUNTIME_CLASS(CGridCellCheck));
-        CGridCellCheck* pCheck = static_cast<CGridCellCheck*>(m_wndGrid.GetCell(i, 1));
-        if (pCheck) {
-            pCheck->SetCheck(FALSE);
-        }
-    }
-
-    m_wndGrid.Invalidate();
-    m_wndGrid.UpdateWindow();
 }
 
 void CPortConfigurationDlg::DoDataExchange(CDataExchange* pDX)
@@ -195,7 +176,13 @@
     for (const auto& item : ports) {
         m_comboPort.AddString(item);
     }
-    m_comboPort.SetCurSel(0); // 榛樿閫夋嫨绗竴涓鍙�
+    if (0 <= m_nCurSelPort && m_nCurSelPort <= 3) {
+        m_comboPort.SetCurSel(m_nCurSelPort);
+        m_comboPort.EnableWindow(FALSE);
+    }
+    else {
+        m_comboPort.SetCurSel(0);
+    }
 
     // 鍒濆鍖栭厤鏂逛笅鎷夋鍐呭
     std::vector<std::string> vecRecipe = RecipeManager::getInstance().getAllPPID();
@@ -216,7 +203,15 @@
 	LoadPortConfigToUI(m_pPort[0]);     // 榛樿鍔犺浇绗竴涓鍙g殑閰嶇疆
 
 	// 璁剧疆瀵硅瘽妗嗘爣棰�
-	SetWindowText(_T("Port Configuration"));
+    if (0 <= m_nCurSelPort && m_nCurSelPort <= 3) {
+        CString strTitle;
+        strTitle.Format(_T("%s Configuration"), ports[m_nCurSelPort]);
+        SetWindowText(strTitle);
+    }
+    else {
+        SetWindowText(_T("Port Configuration"));
+    }
+
 
 	return TRUE;  // return TRUE unless you set the focus to a control
 	// 寮傚父: OCX 灞炴�ч〉搴旇繑鍥� FALSE
@@ -290,34 +285,21 @@
 
     // 鑾峰彇 Grid 琛ㄦ牸涓� Slot 鐘舵�侊紙绗�1~8琛岋級
     for (int i = 1; i <= 8; ++i) {
-        SERVO::SlotConfig slot;
-        slot.nSlotID = i;
+        SERVO::CGlass* pGlass = (SERVO::CGlass*)m_wndGrid.GetItemData(i, 0);
+        if (pGlass != nullptr) {
+            CGridCellCheck* pCheck = dynamic_cast<CGridCellCheck*>(m_wndGrid.GetCell(i, 1));
+            ASSERT(pCheck);
+            pGlass->setScheduledForProcessing(pCheck->GetCheck());
+            pGlass->setType(static_cast<SERVO::MaterialsType>(config.nMaterialType));
 
-        CGridCellCheck* pCheck = static_cast<CGridCellCheck*>(m_wndGrid.GetCell(i, 1));
-        if (pCheck) {
-            slot.isEnabled = pCheck->GetCheck();
+            SERVO::CJobDataS* pJobDataS = pGlass->getJobDataS();
+            pJobDataS->setLotId(config.strLotID.c_str());
+            pJobDataS->setProductId(config.strProductID.c_str());
+            pJobDataS->setOperationId(config.strOperationID.c_str());
+            pJobDataS->setMaterialsType(config.nMaterialType);
         }
-
-        config.vecSlot.push_back(slot);
     }
 
-    int nEqID = GetLoadPortEqID(config.strPortName);
-    if (nEqID < 0) {
-        AfxMessageBox(_T("鏈煡鐨勭鍙e悕绉帮紒"));
-        return;
-    }
-
-    SERVO::CLoadPort* pPort = dynamic_cast<SERVO::CLoadPort*>(theApp.m_model.m_master.getEquipment(nEqID));
-    if (!pPort) {
-        AfxMessageBox(_T("鎵句笉鍒板搴旂殑 LoadPort 璁惧锛�"));
-        return;
-    }
-
-    // 搴旂敤閰嶇疆锛堜緥濡傛祴璇曠敓鎴愮幓鐠冿級
-    if (pPort->testGenerateGlassListFromConfig(config) < 0) {
-		AfxMessageBox(_T("Failed to generate glass list from configuration!"));
-        return;
-	}
 
     OnOK();
 }
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/PortConfigurationDlg.h b/SourceCode/Bond/Servo/PortConfigurationDlg.h
index f08af7f..a8cd23f 100644
--- a/SourceCode/Bond/Servo/PortConfigurationDlg.h
+++ b/SourceCode/Bond/Servo/PortConfigurationDlg.h
@@ -13,6 +13,9 @@
 	CPortConfigurationDlg(CWnd* pParent = nullptr);   // 鏍囧噯鏋勯�犲嚱鏁�
 	virtual ~CPortConfigurationDlg();
 
+public:
+	void setCurSelPort(int sel);
+
 // 瀵硅瘽妗嗘暟鎹�
 #ifdef AFX_DESIGN_TIME
 	enum { IDD = IDD_DIALOG_PORT_CONFIGURATION };
@@ -29,9 +32,10 @@
 	int GetLoadPortEqID(const std::string& strPortName);
 	void LoadPortConfigToUI(SERVO::CLoadPort* pPort);
 	void InitGrid();
-	void FillGrid();
 
+private:
 	SERVO::CLoadPort* m_pPort[4];
+	int m_nCurSelPort;
 
 	CGridCtrl m_wndGrid;
 	CComboBox m_comboPort;
diff --git a/SourceCode/Bond/Servo/Servo.rc b/SourceCode/Bond/Servo/Servo.rc
index eb383bf..2a76253 100644
--- a/SourceCode/Bond/Servo/Servo.rc
+++ b/SourceCode/Bond/Servo/Servo.rc
Binary files differ
diff --git a/SourceCode/Bond/Servo/ServoDlg.cpp b/SourceCode/Bond/Servo/ServoDlg.cpp
index 26b9e62..bde44da 100644
--- a/SourceCode/Bond/Servo/ServoDlg.cpp
+++ b/SourceCode/Bond/Servo/ServoDlg.cpp
@@ -241,6 +241,14 @@
 					}
 				}
 			}
+			else if (RX_CODE_LOADPORT_INUSE == code) {
+				SERVO::CLoadPort* pLoadPort = nullptr;
+				if (pAny->getPtrValue("ptr", (void*&)pLoadPort)) {
+					CPortConfigurationDlg dlg;
+					dlg.setCurSelPort(pLoadPort->getIndex());
+					dlg.DoModal();
+				}
+			}
 
 			pAny->release();
 		}, [&]() -> void {

--
Gitblit v1.9.3