1.将原来的设置CassetteType更新到EFEM的功能,修改为本地保存,因为EFEM不需要这些数据;
2.配置是否需要比较map的一致性;
3.收到EFEM的PortStarus,INUSE状态时,弹出配置对话框;打勾选择要加工的产品;
| | |
| | | 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] |
| | |
| | | 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] |
| | |
| | | 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; |
| | |
| | | ONPRESTOREDJOB onPreStoredJob; |
| | | ONPROCESSSTATE onProcessStateChanged; |
| | | ONMAPMISMATCH onMapMismatch; |
| | | ONPORTINUSE onPortInUse; |
| | | |
| | | } EquipmentListener; |
| | | |
| | | |
| | |
| | | m_pBuddy = nullptr; |
| | | m_nOriginPort = 0; |
| | | m_nOriginSlot = 0; |
| | | m_bScheduledForProcessing = FALSE; |
| | | } |
| | | |
| | | CGlass::~CGlass() |
| | |
| | | slot = m_nOriginSlot; |
| | | } |
| | | |
| | | BOOL CGlass::isScheduledForProcessing() |
| | | { |
| | | return m_bScheduledForProcessing; |
| | | } |
| | | |
| | | void CGlass::setScheduledForProcessing(BOOL bProcessing) |
| | | { |
| | | m_bScheduledForProcessing = bProcessing; |
| | | } |
| | | |
| | | CPath* CGlass::getPath() |
| | | { |
| | | return m_pPath; |
| | |
| | | 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); |
| | |
| | | ReadString(ar, m_strID); |
| | | ar >> m_nOriginPort; |
| | | ar >> m_nOriginSlot; |
| | | ar >> m_bScheduledForProcessing; |
| | | ar >> ullPath; |
| | | if (ullPath != 0) { |
| | | m_pPath = new CPath(); |
| | |
| | | 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); |
| | |
| | | std::string m_strBuddyId; |
| | | int m_nOriginPort; |
| | | int m_nOriginSlot; |
| | | BOOL m_bScheduledForProcessing; /* 是否将加工处理 */ |
| | | }; |
| | | } |
| | | |
| | |
| | | m_bEnable = FALSE; |
| | | m_bAutoChangeEnable = FALSE; |
| | | m_nNextCassetteSequenceNo = 0; |
| | | m_isCompareMapsBeforeProceeding = FALSE; |
| | | } |
| | | |
| | | CLoadPort::~CLoadPort() |
| | |
| | | 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; |
| | | }); |
| | |
| | | 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) |
| | |
| | | |
| | | // 当port状态为InUse, 比较map |
| | | if (m_portStatusReport.getPortStatus() == PORT_INUSE) { |
| | | short scanMap = m_portStatusReport.getJobExistenceSlot(); |
| | | short downMap = getCassetteMap(); |
| | | if (scanMap == downMap) { |
| | | 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 { |
| | |
| | | |
| | | // 抛出到应用层做提示 |
| | | if (m_listener.onMapMismatch != nullptr) { |
| | | m_listener.onMapMismatch(this, scanMap, downMap); |
| | | m_listener.onMapMismatch(this, scanMap, downloadMap); |
| | | } |
| | | } |
| | | } |
| | | else { |
| | | // 抛出到应用层做选择要加工的片子 |
| | | generateGlassList(getScanCassetteMap()); |
| | | if (m_listener.onPortInUse != nullptr) { |
| | | m_listener.onPortInUse(this, getScanCassetteMap()); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | 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) { |
| | |
| | | // test |
| | | code = WOK; |
| | | if (code == WOK) { |
| | | m_cassetteType = type; |
| | | LOGI("<CLoadPort-%d>设置Cassette Type成功.", m_nIndex); |
| | | } |
| | | else { |
| | |
| | | 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; |
| | | } |
| | | |
| | |
| | | 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]; |
| | |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | void CLoadPort::setCompareMapsBeforeProceeding(BOOL bCompare) |
| | | { |
| | | m_isCompareMapsBeforeProceeding = bCompare; |
| | | } |
| | | } |
| | |
| | | void localSetCessetteType(CassetteType type); |
| | | void localSetTransferMode(TransferMode mode); |
| | | void localAutoChangeEnable(BOOL bEnable); |
| | | short getCassetteMap(); |
| | | short getScanCassetteMap(); |
| | | short getDownloadCassetteMap(); |
| | | |
| | | public: |
| | | short getNextCassetteSequenceNo(); |
| | |
| | | int getCassetteMappingState(); |
| | | int getCassetteStatus(); |
| | | int testGenerateGlassList(MaterialsType type); |
| | | int generateGlassList(short map); |
| | | int testGenerateGlassListFromConfig(const SERVO::PortConfig& config); |
| | | |
| | | public: |
| | |
| | | CJobDataA* pJobDataA, |
| | | ONWRITED onWritedBlock); |
| | | CStep* getCassetteCtrlCmdStep(); |
| | | void setCompareMapsBeforeProceeding(BOOL bCompare); |
| | | |
| | | private: |
| | | int decodePortStatusReport(CStep* pStep, const char* pszData, size_t size); |
| | |
| | | BOOL m_bAutoChangeEnable; |
| | | CPortStatusReport m_portStatusReport; |
| | | int m_nNextCassetteSequenceNo; |
| | | |
| | | // 在开始工艺前是否先需要先比较map |
| | | BOOL m_isCompareMapsBeforeProceeding; |
| | | }; |
| | | } |
| | | |
| | |
| | | m_state = MASTERSTATE::READY; |
| | | m_pActiveRobotTask = nullptr; |
| | | m_nLastError = 0; |
| | | m_isCompareMapsBeforeProceeding = FALSE; |
| | | InitializeCriticalSection(&m_criticalSection); |
| | | } |
| | | |
| | |
| | | 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); |
| | |
| | | pEquipment->setID(EQ_ID_LOADPORT1 + index); |
| | | pEquipment->setName(szName); |
| | | pEquipment->setDescription(szName); |
| | | pEquipment->setCompareMapsBeforeProceeding(m_isCompareMapsBeforeProceeding); |
| | | addToEquipmentList(pEquipment); |
| | | |
| | | |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | ONEQVCREVENTREPORT onEqVcrEventReport; |
| | | ONEQDATACHANGED onEqDataChanged; |
| | | ONROBOTTASKEVENT onRobotTaskEvent; |
| | | ONLOADPORTINUSE onLoadPortInUse; |
| | | } MasterListener; |
| | | |
| | | class CMaster |
| | |
| | | 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); } |
| | |
| | | // 错误代码 |
| | | int m_nLastError; |
| | | std::string m_strLastError; |
| | | |
| | | // 在开始工艺前是否先需要先比较map |
| | | BOOL m_isCompareMapsBeforeProceeding; |
| | | }; |
| | | } |
| | | |
| | |
| | | |
| | | // 测试 |
| | | 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; |
| | |
| | | |
| | | void CPagePortProperty::OnCbnSelchangeComboPortCassertType() |
| | | { |
| | | // 由原来的更新到EFEM, 修改为保存到本地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("请等待", "正在操作,请等待..."); |
| | | msgDlg.SetData((DWORD_PTR)this); |
| | |
| | | |
| | | msgDlg.DoModal(); |
| | | g_nMsgDlgShow = 1; |
| | | */ |
| | | } |
| | | |
| | | void CPagePortProperty::OnCbnSelchangeComboPortTransferMode() |
| | |
| | | return m_nPortStatus; |
| | | } |
| | | |
| | | void CPortStatusReport::setPortStatus(short status) |
| | | { |
| | | m_nPortStatus = status; |
| | | } |
| | | |
| | | short CPortStatusReport::getCassetteSequenceNo() |
| | | { |
| | | return m_nCassetteSequenceNo; |
| | |
| | | memcpy(&m_nCassetteStatus, &pszBuffer[index], sizeof(short)); |
| | | index += sizeof(short); |
| | | |
| | | return 15 * 2; |
| | | return 32 * 2; |
| | | } |
| | | |
| | | void CPortStatusReport::getAttributeVector(CAttributeVector& attrubutes, int beginWeight) |
| | |
| | | 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(); |
| | |
| | | public: |
| | | void copyEx(CPortStatusReport& other); |
| | | short getPortStatus(); |
| | | void setPortStatus(short status); |
| | | short getCassetteSequenceNo(); |
| | | std::string& getCassetteId(); |
| | | short getLoadingCassetteType(); |
| | |
| | | bool canPickFromPort(); |
| | | bool isJobExistenceSlot(); |
| | | short getJobExistenceSlot(); |
| | | void setJobExistenceSlot(short map); |
| | | |
| | | private: |
| | | void WriteString(CArchive& ar, std::string& string); |
| | |
| | | #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 */ |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | 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); |
| | |
| | | } |
| | | } |
| | | |
| | | 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; |
| | |
| | | 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); |
| | | |
| | | |
| | |
| | | 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(); |
| | |
| | | SERVO::CMaster& getMaster(); |
| | | void setWorkDir(const char* pszWorkDir); |
| | | void loadPortParams(); |
| | | void setPortCassetteType(unsigned int index, SERVO::CassetteType type); |
| | | int init(); |
| | | int term(); |
| | | |
| | |
| | | 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) |
| | |
| | | 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) { |
| | |
| | | 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) |
| | |
| | | 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(); |
| | |
| | | LoadPortConfigToUI(m_pPort[0]); // 默认加载第一个端口的配置 |
| | | |
| | | // 设置对话框标题 |
| | | 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 |
| | |
| | | |
| | | // 获取 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("未知的端口名称!")); |
| | | 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(); |
| | | } |
| | |
| | | CPortConfigurationDlg(CWnd* pParent = nullptr); // 标准构造函数 |
| | | virtual ~CPortConfigurationDlg(); |
| | | |
| | | public: |
| | | void setCurSelPort(int sel); |
| | | |
| | | // 对话框数据 |
| | | #ifdef AFX_DESIGN_TIME |
| | | enum { IDD = IDD_DIALOG_PORT_CONFIGURATION }; |
| | |
| | | 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; |
| | |
| | | } |
| | | } |
| | | } |
| | | 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 { |