| | |
| | | #include "stdafx.h" |
| | | #include "stdafx.h" |
| | | #include "CEquipment.h" |
| | | #include "ToolUnits.h" |
| | | #include <regex> |
| | | #include "CArm.h" |
| | | #include "CGlassPool.h" |
| | | #include "Servo.h" |
| | | #include "GlassJson.h" |
| | | |
| | | |
| | | namespace SERVO { |
| | |
| | | m_pCclink = nullptr; |
| | | m_nBaseAlarmId = 0; |
| | | m_pArm = nullptr; |
| | | m_processState = PROCESS_STATE::Ready; |
| | | m_blockReadBit = { 0 }; |
| | | m_nTestFlag = 0; |
| | | InitializeCriticalSection(&m_criticalSection); |
| | | } |
| | | |
| | |
| | | void CEquipment::getProperties(std::vector<std::pair<std::string, std::string>>& container) |
| | | { |
| | | container.clear(); |
| | | // 示例:将一些属性添加到容器 |
| | | // 示例:将一些属性添加到容器 |
| | | container.push_back(std::make_pair("DeviceName", "ServoMotor")); |
| | | container.push_back(std::make_pair("SerialNumber", "123456789")); |
| | | container.push_back(std::make_pair("Version", "1.0")); |
| | |
| | | return 0; |
| | | } |
| | | |
| | | void CEquipment::setProcessState(PROCESS_STATE state) |
| | | void CEquipment::setProcessState(int nSlotNo, PROCESS_STATE state) |
| | | { |
| | | m_processState = state; |
| | | onProcessStateChanged(m_processState); |
| | | if (nSlotNo <= 0 || nSlotNo > 8) return; |
| | | |
| | | const auto prevState = m_processState[nSlotNo - 1]; |
| | | m_processState[nSlotNo - 1] = state; |
| | | onProcessStateChanged(nSlotNo, prevState, m_processState[nSlotNo - 1]); |
| | | |
| | | if (m_listener.onProcessStateChanged != nullptr) { |
| | | m_listener.onProcessStateChanged(this, m_processState); |
| | | m_listener.onProcessStateChanged(this, nSlotNo, prevState, m_processState[nSlotNo - 1]); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | void CEquipment::onTimer(UINT nTimerid) |
| | | { |
| | | // 每隔一秒,检查一下ALIVE状态 |
| | | // 每隔一秒,检查一下ALIVE状态 |
| | | |
| | | static int tick = 0; |
| | | tick++; |
| | |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | m_slot[i].serialize(ar); |
| | | CGlass* pGlass = (CGlass *)m_slot[i].getContext(); |
| | | if (pGlass != nullptr) { |
| | | pGlass->serialize(ar); |
| | | if (pGlass != nullptr) { |
| | | const std::string pretty = GlassJson::ToPrettyString(*pGlass); |
| | | CString strPretty = CString(pretty.c_str()); |
| | | ar << strPretty; |
| | | |
| | | CGlass* pBuddy = pGlass->getBuddy(); |
| | | if (pBuddy != nullptr) { |
| | | pBuddy->serialize(ar); |
| | | const std::string prettyBuddy = GlassJson::ToPrettyString(*pBuddy); |
| | | CString strPrettyBuddy = CString(prettyBuddy.c_str()); |
| | | ar << strPrettyBuddy; |
| | | } |
| | | } |
| | | } |
| | |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | m_slot[i].serialize(ar); |
| | | if (m_slot[i].getTempContext() != nullptr) { |
| | | CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass(); |
| | | pGlass->serialize(ar); |
| | | m_slot[i].setContext(pGlass); |
| | | if (pGlass->getBuddy() != nullptr) { |
| | | CGlass* pBuddy = theApp.m_model.m_glassPool.allocaGlass(); |
| | | pBuddy->serialize(ar); |
| | | pGlass->forceSetBuddy(pBuddy); |
| | | CString strPretty; |
| | | std::string pretty; |
| | | ar >> strPretty; |
| | | pretty = (LPTSTR)(LPCTSTR)strPretty; |
| | | if (!pretty.empty()) { |
| | | CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass(); |
| | | GlassJson::FromString(pretty, *pGlass); |
| | | m_slot[i].setContext(pGlass); |
| | | |
| | | if (!pGlass->getBuddyId().empty()) { |
| | | CGlass* pBuddy = theApp.m_model.m_glassPool.allocaGlass(); |
| | | CString strPrettyBuddy; |
| | | std::string prettyBuddy; |
| | | ar >> strPrettyBuddy; |
| | | prettyBuddy = (LPTSTR)(LPCTSTR)strPrettyBuddy; |
| | | GlassJson::FromString(prettyBuddy, *pBuddy); |
| | | pGlass->forceSetBuddy(pBuddy); |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | // 梳理各玻璃之间的绑定关系 |
| | | |
| | | // 梳理各玻璃之间的绑定关系 |
| | | /* |
| | | Lock(); |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | |
| | | CGlass* pBudy = (CGlass*)m_slot[j].getContext(); |
| | | if (pBudy != nullptr && strBuddyId.compare(pBudy->getID()) == 0) { |
| | | pGlass->setBuddy(pBudy); |
| | | TRACE("绑定关系: %s <- %s\n", pGlass->getID().c_str(), pBudy->getID().c_str()); |
| | | TRACE("绑定关系: %s <- %s\n", pGlass->getID().c_str(), pBudy->getID().c_str()); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | */ |
| | | |
| | | // 连接信号解释和保存 |
| | | // 连接信号解释和保存 |
| | | BOOL bFlag; |
| | | int index = 0; |
| | | for (int i = 0; i < 8; i++) { |
| | |
| | | } |
| | | |
| | | |
| | | // 其它信号及响应 |
| | | // 其它信号及响应 |
| | | index = 0x540; |
| | | |
| | | |
| | |
| | | m_alive.flag = bFlag; |
| | | m_alive.count = 0; |
| | | |
| | | // ״̬ |
| | | // 状态 |
| | | if (!m_alive.alive) { |
| | | m_alive.alive = TRUE; |
| | | if (m_listener.onAlive != nullptr) { |
| | |
| | | } |
| | | |
| | | |
| | | // 以下根据信号做流程处理 |
| | | // 以下根据信号做流程处理 |
| | | for (int i = 0; i < 7; i++) { |
| | | CHECK_READ_STEP_SIGNAL(STEP_ID_EQMODE_CHANGED + i, pszData, size); |
| | | } |
| | |
| | | // process data report |
| | | CHECK_READ_STEP_SIGNAL(STEP_ID_PROCESS_DATA_REPORT, pszData, size); |
| | | |
| | | // 配方改变 |
| | | // FAC Data report |
| | | // CHECK_READ_STEP_SIGNAL(STEP_ID_FAC_DATA_REPORT, pszData, size); |
| | | { |
| | | SERVO::CStep* pStep = getStep(STEP_ID_FAC_DATA_REPORT); |
| | | if (pStep != nullptr) { |
| | | ((CReadStep*)pStep)->onReadSignal(TRUE); |
| | | } |
| | | } |
| | | |
| | | |
| | | // 配方改变 |
| | | CHECK_READ_STEP_SIGNAL(STEP_ID_CURRENT_RECIPE_CHANGE_REPORT, pszData, size); |
| | | |
| | | // 主配方上报 |
| | | // 主配方上报 |
| | | CHECK_READ_STEP_SIGNAL(STEP_ID_MASTER_RECIPE_LIST_REPORT, pszData, size); |
| | | |
| | | // 配方参数 |
| | | CHECK_WRITE_STEP_SIGNAL(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pszData, size); |
| | | CHECK_READ_STEP_SIGNAL(STEP_ID_RECIPE_PARAMETER_REPORT, pszData, size); |
| | | |
| | | |
| | | // CIM Mode |
| | | CHECK_WRITE_STEP_SIGNAL(STEP_ID_CIMMODE_CHANGED_CMD_REPLY, pszData, size); |
| | |
| | | else if (isCimMessageConfirmStep(pStep)) { |
| | | SERVO::CEqReadIntStep* pEqReadIntStep = (SERVO::CEqReadIntStep*)pStep; |
| | | int value = pEqReadIntStep->getValue(); |
| | | // 此处将value按高低位拆分为message id和panel no. |
| | | // 可能还需要上报到cim |
| | | // 此处将value按高低位拆分为message id和panel no. |
| | | // 可能还需要上报到cim |
| | | short msgId, panelNo; |
| | | msgId = (value & 0xffff0000 >> 16); |
| | | panelNo = (value & 0xffff); |
| | |
| | | m_listener.onVcrEventReport(this, pVcrEventReport); |
| | | } |
| | | |
| | | // 0426, 先固定返回1(OK) |
| | | // 0426, 先固定返回1(OK) |
| | | pEqVcrEventStep->setReturnCode(1); |
| | | return 1; |
| | | } |
| | |
| | | |
| | | CPin* CEquipment::addPin(PinType type, char* pszName) |
| | | { |
| | | // 不允许名字添加重复的pin |
| | | // 不允许名字添加重复的pin |
| | | CPin* pPin = getPin(pszName); |
| | | if (pPin != nullptr) return nullptr; |
| | | |
| | | |
| | | // 添加到Pin列表,看是输入pin或输出pin |
| | | // 添加到Pin列表,看是输入pin或输出pin |
| | | if (type == PinType::INPUT) { |
| | | pPin = new CPin(this, type, pszName); |
| | | m_inputPins.push_back(pPin); |
| | |
| | | return m_recipesManager.getRecipeList(unitNo); |
| | | } |
| | | |
| | | bool CEquipment::saveRecipeList(int unitNo, std::string& strFilepath) |
| | | { |
| | | return m_recipesManager.saveRecipeList(unitNo, strFilepath); |
| | | } |
| | | |
| | | bool CEquipment::readRecipeList(int unitNo, std::string& strFilepath) |
| | | { |
| | | return m_recipesManager.readRecipeList(unitNo, strFilepath); |
| | | } |
| | | |
| | | int CEquipment::recvIntent(CPin* pPin, CIntent* pIntent) |
| | | { |
| | | ASSERT(pPin); |
| | |
| | | CEquipment* pFromEq = pFromPin->getEquipment(); |
| | | ASSERT(pFromEq); |
| | | |
| | | LOGI("<CEquipment><%s-%s>收到来自<%s.%s>的Intent<%d,%s,0x%x>", |
| | | LOGD("<CEquipment><%s-%s>收到来自<%s.%s>的Intent<%d,%s,0x%x>", |
| | | this->getName().c_str(), |
| | | pPin->getName().c_str(), |
| | | pFromEq->getName().c_str(), |
| | |
| | | |
| | | |
| | | |
| | | // 以下解释处理数据 |
| | | // 以下解释处理数据 |
| | | int code = pIntent->getCode(); |
| | | |
| | | |
| | | // 测试 |
| | | // 测试 |
| | | if (code == FLOW_TEST) { |
| | | AfxMessageBox(pIntent->getMsg()); |
| | | } |
| | |
| | | return -1; |
| | | } |
| | | |
| | | // 找到指定的glass id, |
| | | // 找到指定的glass id, |
| | | Lock(); |
| | | CGlass* pContext = nullptr; |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | |
| | | Unlock(); |
| | | |
| | | |
| | | if (m_processState != PROCESS_STATE::Ready) { |
| | | setProcessState(PROCESS_STATE::Ready); |
| | | if (m_processState[port] != PROCESS_STATE::Ready) { |
| | | setProcessState(port, PROCESS_STATE::Ready); |
| | | } |
| | | |
| | | if (m_listener.onDataChanged != nullptr) { |
| | |
| | | |
| | | ASSERT(pGlass); |
| | | Lock(); |
| | | pGlass->addPath(m_nID, getSlotUnit(putSlot)); |
| | | pGlass->addPath(m_nID, getSlotUnit(putSlot), putSlot); |
| | | CGlass* pBuddy = pGlass->getBuddy(); |
| | | if (pBuddy != nullptr) pBuddy->addPath(m_nID, getSlotUnit(putSlot), putSlot); |
| | | m_slot[putSlot - 1].setContext(pGlass); |
| | | pGlass->release(); // tempFetchOut需要调用一次release |
| | | pGlass->release(); // tempFetchOut需要调用一次release |
| | | Unlock(); |
| | | |
| | | /* |
| | | if (m_processState != PROCESS_STATE::Processing) { |
| | | setProcessState(PROCESS_STATE::Processing); |
| | | } |
| | | */ |
| | | |
| | | if (m_listener.onDataChanged != nullptr) { |
| | | m_listener.onDataChanged(this, EDCC_STORED_JOB); |
| | |
| | | |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | int CEquipment::getAllGlass(std::vector<CGlass*>& glasses) |
| | | { |
| | | Lock(); |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | if (!m_slot[i].isEnable()) continue; |
| | | CGlass* pGlass = (CGlass*)m_slot[i].getContext(); |
| | | if (pGlass != nullptr) { |
| | | pGlass->addRef(); |
| | | glasses.push_back(pGlass); |
| | | } |
| | | } |
| | | Unlock(); |
| | | |
| | | return (int)glasses.size(); |
| | | } |
| | | |
| | | CJobDataS* CEquipment::getJobDataSWithCassette(int cassetteSequenceNo, int jobSequenceNo) |
| | |
| | | return -1; |
| | | } |
| | | |
| | | LOGI("<CEquipment-%s>准备设置DispatchingMode<%d>", m_strName.c_str(), (int)mode); |
| | | LOGI("<CEquipment-%s>准备设置DispatchingMode<%d>", m_strName.c_str(), (int)mode); |
| | | if (onWritedBlock != nullptr) { |
| | | pStep->writeShort((short)mode, onWritedBlock); |
| | | } |
| | | else { |
| | | pStep->writeShort((short)mode, [&, mode](int code) -> int { |
| | | if (code == WOK) { |
| | | LOGI("<CEquipment-%s>设置DispatchingMode成功.", m_strName.c_str()); |
| | | LOGI("<CEquipment-%s>设置DispatchingMode成功.", m_strName.c_str()); |
| | | } |
| | | else { |
| | | LOGI("<CEquipment-%s>设置DispatchingMode失败,code:%d", m_strName.c_str(), code); |
| | | LOGE("<CEquipment-%s>设置DispatchingMode失败,code:%d", m_strName.c_str(), code); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | } |
| | | |
| | | unsigned short operationMode = (unsigned short)((unsigned short)mode + getIndexerOperationModeBaseValue()); |
| | | LOGI("<CEquipment-%s>准备设置indexerOperationMode<%d>", m_strName.c_str(), (int)mode); |
| | | LOGI("<CEquipment-%s>准备设置indexerOperationMode<%d>", m_strName.c_str(), (int)mode); |
| | | pStep->writeShort(operationMode, [&, pStep, mode, onWritedRetBlock](int code) -> int { |
| | | int retCode = 0; |
| | | if (code == WOK) { |
| | | LOGI("<CEquipment-%s>设置indexerOperationMode成功.", m_strName.c_str()); |
| | | LOGI("<CEquipment-%s>设置indexerOperationMode成功.", m_strName.c_str()); |
| | | const char* pszRetData = nullptr; |
| | | pStep->getReturnData(pszRetData); |
| | | ASSERT(pszRetData); |
| | | retCode = (unsigned int)CToolUnits::toInt16(pszRetData); |
| | | LOGI("<CEquipment-%s>返回值: %d", m_strName.c_str(), retCode); |
| | | LOGI("<CEquipment-%s>返回值: %d", m_strName.c_str(), retCode); |
| | | } |
| | | else { |
| | | LOGI("<CEquipment-%s>设置indexerOperationMode失败,code:%d", m_strName.c_str(), code); |
| | | LOGE("<CEquipment-%s>设置indexerOperationMode失败,code:%d", m_strName.c_str(), code); |
| | | } |
| | | |
| | | if (onWritedRetBlock != nullptr) { |
| | |
| | | return -1; |
| | | } |
| | | |
| | | LOGI("<CEquipment-%s>正在请求单元<%d>主配方列表", m_strName.c_str(), unitNo); |
| | | LOGI("<CEquipment-%s>正在请求单元<%d>主配方列表", m_strName.c_str(), unitNo); |
| | | m_recipesManager.setOnSyncingStateChanged(block); |
| | | if (m_recipesManager.syncing() != 0) { |
| | | return -2; |
| | | } |
| | | pStep->writeShort(unitNo, [&, unitNo](int code) -> int { |
| | | if (code == WOK) { |
| | | LOGI("<CEquipment-%s>请求单元<%d>主配方列表成功,正在等待数据.", m_strName.c_str(), unitNo); |
| | | LOGI("<CEquipment-%s>请求单元<%d>主配方列表成功,正在等待数据.", m_strName.c_str(), unitNo); |
| | | } |
| | | else { |
| | | m_recipesManager.syncFailed(); |
| | | LOGI("<CEquipment-%s>请求单元<%d>主配方列表失败,code:%d", m_strName.c_str(), unitNo, code); |
| | | LOGE("<CEquipment-%s>请求单元<%d>主配方列表失败,code:%d", m_strName.c_str(), unitNo, code); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | return 0; |
| | | } |
| | | |
| | | int CEquipment::recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo) |
| | | int CEquipment::recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo, ONSYNCINGSTATECHANGED block) |
| | | { |
| | | SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(STEP_EQ_MASTER_RECIPE_LIST_REQ); |
| | | LOGI("<CEquipment-%s>正在请求单元<%d>主配参数列表", m_strName.c_str(), unitNo); |
| | | m_recipesManager.setOnSyncingStateChanged(block); |
| | | if (m_recipesManager.syncing() != 0) { |
| | | return -2; |
| | | } |
| | | |
| | | SERVO::CEqWriteStep* pStep = (SERVO::CEqWriteStep*)getStepWithName(STEP_EQ_RECIPE_PARAMETER_REQ); |
| | | if (pStep == nullptr) { |
| | | return -1; |
| | | } |
| | | |
| | | LOGI("<CEquipment-%s>正在请求单元<%d>主配方列表", m_strName.c_str(), unitNo); |
| | | if (m_recipesManager.syncing() != 0) { |
| | | return -2; |
| | | } |
| | | pStep->writeShort(unitNo, [&, unitNo](int code) -> int { |
| | | char szBuffer[14 * 2] = {0}; |
| | | int index = 0; |
| | | memcpy(&szBuffer[index], &masterRecipeId, sizeof(short)); |
| | | index += sizeof(short); |
| | | memcpy(&szBuffer[index], &localRecipeId, sizeof(short)); |
| | | index += sizeof(short); |
| | | memcpy(&szBuffer[index], &unitNo, sizeof(short)); |
| | | |
| | | pStep->writeDataEx(szBuffer, 14 * 2, [&, unitNo](int code) -> int { |
| | | if (code == WOK) { |
| | | LOGI("<CEquipment-%s>请求单元<%d>主配方列表成功,正在等待数据.", m_strName.c_str(), unitNo); |
| | | LOGI("<CEquipment-%s>请求单元<%d>主配方参数列表成功,正在等待数据.", m_strName.c_str(), unitNo); |
| | | } |
| | | else { |
| | | m_recipesManager.syncFailed(); |
| | | LOGI("<CEquipment-%s>请求单元<%d>主配方列表失败,code:%d", m_strName.c_str(), unitNo, code); |
| | | LOGE("<CEquipment-%s>请求单元<%d>主配方参数列表失败,code:%d", m_strName.c_str(), unitNo, code); |
| | | } |
| | | |
| | | return 0; |
| | | }); |
| | | }); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | |
| | | return nullptr; |
| | | } |
| | | |
| | | CSlot* CEquipment::isSlotAvailable(unsigned int slot) |
| | | { |
| | | if (slot >= 8) return nullptr; |
| | | if (!m_slot[slot].isEnable()) return nullptr; |
| | | if (m_slot[slot].isLock()) return nullptr; |
| | | if (!m_slot[slot].isEmpty()) return nullptr; |
| | | int lsPath = m_slot[slot].getLinkSignalPath(); |
| | | if (!m_bLinkSignalToDownstream[lsPath][SIGNAL_UPSTREAM_INLINE] |
| | | || m_bLinkSignalToDownstream[lsPath][SIGNAL_UPSTREAM_TROUBLE] |
| | | || !m_bLinkSignalToDownstream[lsPath][SIGNAL_INTERLOCK] |
| | | || !m_bLinkSignalToDownstream[lsPath][SIGNAL_RECEIVE_ABLE]) return nullptr; |
| | | |
| | | return &m_slot[slot]; |
| | | } |
| | | |
| | | CSlot* CEquipment::getNonEmptySlot(MaterialsType putSlotType) |
| | | { |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | |
| | | return nullptr; |
| | | } |
| | | |
| | | CSlot* CEquipment::getProcessedSlot(MaterialsType putSlotType) |
| | | CSlot* CEquipment::getProcessedSlot(MaterialsType putSlotType, BOOL bJobMode/* = FALSE*/) |
| | | { |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 001"); |
| | | if (!m_slot[i].isEnable()) continue; |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 002"); |
| | | if (m_slot[i].isLock()) continue; |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 003"); |
| | | CGlass* pGlass = (CGlass*)m_slot[i].getContext(); |
| | | if (!isSlotProcessed(i)) continue; |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 004"); |
| | | if (pGlass == nullptr) continue; |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 005"); |
| | | if (!pGlass->isScheduledForProcessing()) continue; |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 006"); |
| | | if (bJobMode && pGlass->getProcessJob() == nullptr) continue; |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 007"); |
| | | if(pGlass->getInspResult(m_nID, 0) == InspResult::Fail) continue; |
| | | int lsPath = m_slot[i].getLinkSignalPath(); |
| | | if(!m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_INLINE] |
| | | || m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_TROUBLE] |
| | | || !m_bLinkSignalToUpstream[lsPath][SIGNAL_INTERLOCK] |
| | | || !m_bLinkSignalToUpstream[lsPath][SIGNAL_SEND_ABLE] ) continue; |
| | | |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 008"); |
| | | MaterialsType glassType = pGlass->getType(); |
| | | if (glassType == MaterialsType::G1 && putSlotType == MaterialsType::G2) continue; |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 009"); |
| | | if (glassType == MaterialsType::G2 && putSlotType == MaterialsType::G1) continue; |
| | | |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 00a"); |
| | | return &m_slot[i]; |
| | | } |
| | | |
| | |
| | | return nullptr; |
| | | } |
| | | |
| | | CSlot* CEquipment::getProcessedSlotCt(unsigned int slot) |
| | | { |
| | | if (slot >= 8) return nullptr; |
| | | if (!m_slot[slot].isEnable()) return nullptr; |
| | | if (m_slot[slot].isLock()) return nullptr; |
| | | CGlass* pGlass = (CGlass*)m_slot[slot].getContext(); |
| | | if (pGlass == nullptr) return nullptr; |
| | | int lsPath = m_slot[slot].getLinkSignalPath(); |
| | | if (!m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_INLINE] |
| | | || m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_TROUBLE] |
| | | || !m_bLinkSignalToUpstream[lsPath][SIGNAL_INTERLOCK] |
| | | || !m_bLinkSignalToUpstream[lsPath][SIGNAL_SEND_ABLE]) return nullptr; |
| | | |
| | | return &m_slot[slot]; |
| | | } |
| | | |
| | | CSlot* CEquipment::getInspFailSlot() |
| | | { |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | |
| | | 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] |
| | |
| | | { |
| | | if (index >= SLOT_MAX) return nullptr; |
| | | return &m_slot[index]; |
| | | } |
| | | |
| | | CSlot* CEquipment::getSlotWithNo(int slotNo) |
| | | { |
| | | CSlot* pSlot = nullptr; |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | if (!m_slot[i].isEnable()) continue; |
| | | if (m_slot[i].getNo() != slotNo) continue; |
| | | pSlot = &m_slot[i]; |
| | | break; |
| | | } |
| | | |
| | | return pSlot; |
| | | } |
| | | |
| | | CGlass* CEquipment::getAnyGlass() |
| | |
| | | if (m_slot[slotIndex].getContext() != nullptr) return FALSE; |
| | | |
| | | return TRUE; |
| | | } |
| | | |
| | | BOOL CEquipment::slotHasGlass(int slotIndex/* = 0*/) |
| | | { |
| | | ASSERT(slotIndex < 8); |
| | | CGlass* pGlass = (CGlass*)m_slot[slotIndex].getContext(); |
| | | return (pGlass != nullptr); |
| | | } |
| | | |
| | | int CEquipment::removeGlass(int slotNo) |
| | |
| | | int nRet = processData.unserialize(&pszData[0], (int)size); |
| | | if (nRet < 0) return nRet; |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | CAttributeVector& attrubutes = pStep->attributeVector(); |
| | | processData.getAttributeVector(attrubutes, weight); |
| | | onProcessData(&processData); |
| | | |
| | | |
| | | |
| | | // 找到玻璃,关联数据 |
| | | CGlass* pGlass = this->getGlassWithCassette(processData.getCassetteSequenceNo(), |
| | | processData.getJobSequenceNo()); |
| | | if (pGlass == nullptr) { |
| | | LOGE("<CEquipment-%s>找不到对应Glass, 关联工艺参数失败。CassetteSequenceNo:%d/%d", |
| | | this->getName().c_str(), |
| | | processData.getCassetteSequenceNo(), |
| | | processData.getJobSequenceNo()); |
| | | return -1; |
| | | } |
| | | |
| | | auto rawData = processData.getParamsRawData(); |
| | | std::vector<CParam> tempParams; |
| | | this->parsingProcessData((const char*)rawData.data(), rawData.size(), tempParams); |
| | | int n = processData.getTotalParameter(); |
| | | std::vector<CParam> params(tempParams.begin(), tempParams.begin() + (std::min)(n, (int)tempParams.size())); |
| | | pGlass->addParams(params); |
| | | if (m_listener.onProcessDataReport != nullptr) { |
| | | m_listener.onProcessDataReport(this, params); |
| | | } |
| | | |
| | | // 关联的Glass也要更新 |
| | | CGlass* pBuddy = pGlass->getBuddy(); |
| | | LOGI("<Equipment-%s>decodeProcessDataReport pBuddy=%x %s", getName().c_str(), pBuddy, pGlass->getID().c_str()); |
| | | if (pBuddy != nullptr) { |
| | | LOGI("<Equipment-%s>decodeProcessDataReport addParams pBuddy=%x %s", getName().c_str(), pBuddy, pGlass->getID().c_str()); |
| | | pBuddy->addParams(params); |
| | | if (m_listener.onProcessDataReport != nullptr) { |
| | | m_listener.onProcessDataReport(this, params); |
| | | } |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | |
| | | int nRet = jobDataS.unserialize(&pszData[0], (int)size); |
| | | if (nRet < 0) return nRet; |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | CAttributeVector& attrubutes = pStep->attributeVector(); |
| | | jobDataS.getAttributeVector(attrubutes, weight); |
| | |
| | | LOGI("<CEquipment-%s>onReceivedJob.", m_strName.c_str()); |
| | | |
| | | |
| | | // 可以在此更新JobDataS数据了 |
| | | // 可以在此更新JobDataS数据了 |
| | | int nRet = ((CArm*)m_pArm)->glassUpdateJobDataS(pJobDataS); |
| | | if (nRet < 0) { |
| | | LOGE("<CEquipment-%s>onReceivedJob,更新JobDataS失败,glassUpdateJobDataS返回%d", |
| | | LOGE("<CEquipment-%s>onReceivedJob,更新JobDataS失败,glassUpdateJobDataS返回%d", |
| | | m_strName.c_str(), nRet); |
| | | } |
| | | |
| | |
| | | int nRet = jobDataS.unserialize(&pszData[0], (int)size); |
| | | if (nRet < 0) return nRet; |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | CAttributeVector& attrubutes = pStep->attributeVector(); |
| | | jobDataS.getAttributeVector(attrubutes, weight); |
| | |
| | | index += sizeof(short); |
| | | |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | pStep->addAttribute(new CAttribute("UnitOrPort", |
| | | std::to_string(unitOrPort).c_str(), "", weight++)); |
| | |
| | | return fetchedOutJob(port, pJobDataB); |
| | | } |
| | | |
| | | // 数据异常,处理或显示 |
| | | // 数据异常,处理或显示 |
| | | LOGI("<CEquipment-%s>onFetchedOutJob Error.ort:%d|GlassId:%s", |
| | | m_strName.c_str(), port, pJobDataB->getGlassId().c_str()); |
| | | return -1; |
| | |
| | | index += sizeof(short); |
| | | |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | pStep->addAttribute(new CAttribute("UnitOrPort", |
| | | std::to_string(unitOrPort).c_str(), "", weight++)); |
| | |
| | | int CEquipment::decodeVCREventReport(CStep* pStep, const char* pszData, size_t size) |
| | | { |
| | | CVcrEventReport vcrEventReport; |
| | | vcrEventReport.unserialize(pszData, size); |
| | | vcrEventReport.unserialize(pszData, (int)size); |
| | | LOGI("<CEquipment-%s>decodeVCREventReport<Result:%d, GlassId:%s>\n", m_strName.c_str(), |
| | | vcrEventReport.getVcrResult(), |
| | | vcrEventReport.getGlassId().c_str()); |
| | | |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | // 更新Glass的ID |
| | | CGlass* pGlass = getGlassWithCassette(vcrEventReport.getCassetteSequenceNo(), |
| | | vcrEventReport.getJobSequenceNo()); |
| | | if (pGlass != nullptr) { |
| | | pGlass->setID(vcrEventReport.getGlassId().c_str()); |
| | | } |
| | | |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | CAttributeVector& attrubutes = pStep->attributeVector(); |
| | | vcrEventReport.getAttributeVector(attrubutes, weight); |
| | | |
| | | // 0426, 先固定返回1(OK) |
| | | |
| | | // 0426, 先固定返回1(OK) |
| | | ((CReadStep*)pStep)->setReturnCode((short)VCR_Reply_Code::OK); |
| | | |
| | | |
| | | return 0; |
| | | } |
| | |
| | | index += 256 * 2; |
| | | |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | pStep->addAttribute(new CAttribute("CassetteNo", |
| | | std::to_string(cassetteNo).c_str(), "", weight++)); |
| | |
| | | strPanelGradeData.c_str(), "", weight++)); |
| | | |
| | | |
| | | // 更新检测结果 |
| | | // 更新检测结果 |
| | | CGlass* pGlass = getGlassWithCassette(cassetteNo, jobSequenceNo); |
| | | if (pGlass == nullptr) { |
| | | LOGE("<CEquipment-%s>更新Panel Data失败,找不到对应的Glass.cassetteNo=%d, jobSequenceNo=%d", |
| | | LOGE("<CEquipment-%s>更新Panel Data失败,找不到对应的Glass.cassetteNo=%d, jobSequenceNo=%d", |
| | | getName().c_str(), cassetteNo, jobSequenceNo); |
| | | return -1; |
| | | } |
| | | pGlass->setInspResult(m_nID, 0, judgeStringToInspResult(strPanelJudgeData)); |
| | | auto result = judgeStringToInspResult(strPanelJudgeData); |
| | | pGlass->setInspResult(m_nID, 0, result); |
| | | |
| | | if (m_listener.onPanelDataReport != nullptr) { |
| | | m_listener.onPanelDataReport(this, pGlass); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int CEquipment::decodeFacDataReport(CStep* pStep, const char* pszData, size_t size) |
| | | { |
| | | int index = 0; |
| | | std::string strSvTimeRecord, strSvData; |
| | | CToolUnits::convertString(&pszData[index], 8 * 2, strSvTimeRecord); |
| | | index += 128 * 2; |
| | | CToolUnits::convertString(&pszData[index], 640 * 2, strSvData); |
| | | index += 256 * 2; |
| | | CSVData svData; |
| | | int nRet = svData.unserialize(&pszData[0], (int)size); |
| | | if (nRet < 0) return nRet; |
| | | m_svDatas.push_back(svData); |
| | | |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | pStep->addAttribute(new CAttribute("SV Time Record", |
| | | strSvTimeRecord.c_str(), "", weight++)); |
| | | pStep->addAttribute(new CAttribute("SV Data", |
| | | strSvData.c_str(), "", weight++)); |
| | | |
| | | if (m_listener.onSVDataReport != nullptr) { |
| | | m_listener.onSVDataReport(this, &svData); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | pStep->addAttribute(new CAttribute("CassetteSequenceNo", |
| | | (std::to_string(cassetteSequenceNo)).c_str(), "", weight++)); |
| | |
| | | year, month, day, hour, minute, second |
| | | ); |
| | | |
| | | CGlass* pGlass = getGlassFromSlot(slotNo); |
| | | if (pGlass == nullptr) { |
| | | LOGE("<CEquipment-%s>decodeJobProcessStartReport, 找不到对应glass", getName().c_str()); |
| | | } |
| | | if (slotNo <= 0 || slotNo > 8) return -1; |
| | | |
| | | if (m_processState != PROCESS_STATE::Processing) { |
| | | setProcessState(PROCESS_STATE::Processing); |
| | | if (m_processState[slotNo -1] != PROCESS_STATE::Processing) { |
| | | Lock(); |
| | | m_svDatas.clear(); |
| | | Unlock(); |
| | | setProcessState(slotNo, PROCESS_STATE::Processing); |
| | | } |
| | | |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | pStep->addAttribute(new CAttribute("CassetteNo", |
| | | std::to_string(cassetteNo).c_str(), "", weight++)); |
| | |
| | | ); |
| | | |
| | | |
| | | if (m_processState != PROCESS_STATE::Complete) { |
| | | setProcessState(PROCESS_STATE::Complete); |
| | | } |
| | | |
| | | CGlass* pGlass = getGlassFromSlot(slotNo); |
| | | if (m_processState[slotNo - 1] != PROCESS_STATE::Complete) { |
| | | setProcessState(slotNo, PROCESS_STATE::Complete); |
| | | } |
| | | |
| | | if (pGlass == nullptr) { |
| | | LOGE("<CEquipment-%s>decodeJobProcessEndReport, 找不到对应glass", getName().c_str()); |
| | | LOGE("<CEquipment-%s>decodeJobProcessEndReport, 找不到对应glass", getName().c_str()); |
| | | } |
| | | else { |
| | | CJobDataS* pJs = pGlass->getJobDataS(); |
| | | if (pJs->getCassetteSequenceNo() == cassetteNo |
| | | && pJs->getJobSequenceNo() == jobSequenceNo) { |
| | | pGlass->processEnd(m_nID, getSlotUnit(slotNo)); |
| | | if (m_processState != PROCESS_STATE::Complete) { |
| | | setProcessState(PROCESS_STATE::Complete); |
| | | } |
| | | } |
| | | else { |
| | | LOGE("<CEquipment-%s>decodeJobProcessEndReport, jobSequenceNo或jobSequenceNo不匹配", |
| | | LOGE("<CEquipment-%s>decodeJobProcessEndReport, jobSequenceNo或jobSequenceNo不匹配", |
| | | getName().c_str()); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | // 缓存Attribute,用于调试时显示信息 |
| | | unsigned int weight = 201; |
| | | pStep->addAttribute(new CAttribute("CassetteNo", |
| | | std::to_string(cassetteNo).c_str(), "", weight++)); |
| | |
| | | LOGI("<CEquipment-%s>onPreStoredJob:port:%d|GlassId:%s", |
| | | m_strName.c_str(), port, pJobDataB->getGlassId().c_str()); |
| | | |
| | | // 当前要存片,之前肯定有拔片,因此片子在Arm那里 |
| | | // 当前要存片,之前肯定有拔片,因此片子在Arm那里 |
| | | CGlass* pGlass = ((CArm*)m_pArm)->getGlassFromSlot(1); |
| | | if (pGlass == nullptr) { |
| | | LOGE("<CFliper-%s>onPreStoredJob,缓存中没有找到对应的Glass(CassetteSequenceNo:%d, JobSequenceNo:%d),请检查数据,注意风险。", m_strName.c_str(), |
| | | LOGE("<CFliper-%s>onPreStoredJob,缓存中没有找到对应的Glass(CassetteSequenceNo:%d, JobSequenceNo:%d),请检查数据,注意风险。", m_strName.c_str(), |
| | | pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo()); |
| | | return FALSE; |
| | | } |
| | |
| | | CJobDataS* pJobDataS = pGlass->getJobDataS(); |
| | | ASSERT(pJobDataS); |
| | | if (!compareJobData(pJobDataB, pJobDataS)) { |
| | | LOGE("<CEquipemnt-%s>onPreStoredJob,JobData数据不匹配(JobDataB(%d, %d),JobDataS(%d, %d)), 注意排查风险!", m_strName.c_str(), |
| | | LOGE("<CEquipemnt-%s>onPreStoredJob,JobData数据不匹配(JobDataB(%d, %d),JobDataS(%d, %d)), 注意排查风险!", m_strName.c_str(), |
| | | pJobDataB->getCassetteSequenceNo(), pJobDataB->getJobSequenceNo(), |
| | | pJobDataS->getCassetteSequenceNo(), pJobDataS->getJobSequenceNo()); |
| | | return FALSE; |
| | | } |
| | | |
| | | // 如果没有可用位置,报错 |
| | | // 如果没有可用位置,报错 |
| | | Lock(); |
| | | CSlot* pSlot = getSlot(putSlot - 1); |
| | | ASSERT(pSlot); |
| | | if (pSlot->getContext() != nullptr) { |
| | | Unlock(); |
| | | LOGE("<CEquipemnt-%s>onPreStoredJob,指定slot(port:%d)有料,请注意风险!", m_strName.c_str(), port); |
| | | LOGE("<CEquipemnt-%s>onPreStoredJob,指定slot(port:%d)有料,请注意风险!", m_strName.c_str(), port); |
| | | return FALSE; |
| | | } |
| | | Unlock(); |
| | |
| | | return storedJob(port, pJobDataB, putSlot); |
| | | } |
| | | |
| | | // 数据异常,处理或显示 |
| | | // 数据异常,处理或显示 |
| | | LOGI("<CEquipment-%s>onStoredJob Error.port:%d|GlassId:%s", |
| | | m_strName.c_str(), port, pJobDataB->getGlassId().c_str()); |
| | | return -1; |
| | |
| | | } |
| | | |
| | | /* |
| | | * 当从CC-Link检测到设备Send Able为On时调用此函数 |
| | | * 可能会多次重复调用(根据扫描频率), 注意防呆 |
| | | * 当从CC-Link检测到设备Send Able为On时调用此函数 |
| | | * 可能会多次重复调用(根据扫描频率), 注意防呆 |
| | | */ |
| | | int CEquipment::onSendAble(int port) |
| | | { |
| | | LOGI("<CEquipment-%s>onSendAble.port:%d", m_strName.c_str(), port); |
| | | // LOGI("<CEquipment-%s>onSendAble.port:%d", m_strName.c_str(), port); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int CEquipment::onReceiveAble(int port) |
| | | { |
| | | LOGI("<CEquipment-%s>onReceiveAble.port:%d", m_strName.c_str(), port); |
| | | // LOGI("<CEquipment-%s>onReceiveAble.port:%d", m_strName.c_str(), port); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | int CEquipment::onProcessStateChanged(PROCESS_STATE state) |
| | | int CEquipment::onProcessStateChanged(int nSlotNo, PROCESS_STATE prevState, PROCESS_STATE state) |
| | | { |
| | | return 0; |
| | | } |
| | |
| | | |
| | | return InspResult::NotInspected; |
| | | } |
| | | } |
| | | |
| | | float CEquipment::toFloat(const char* pszAddr) |
| | | { |
| | | BYTE szBuffer[4]; |
| | | szBuffer[0] = pszAddr[0]; |
| | | szBuffer[1] = pszAddr[1]; |
| | | szBuffer[2] = pszAddr[2]; |
| | | szBuffer[3] = pszAddr[3]; |
| | | float f = 0.0; |
| | | memcpy(&f, szBuffer, 4); |
| | | |
| | | return f; |
| | | } |
| | | |
| | | int CEquipment::parsingParams(const char* pszData, size_t size, std::string& strOut) |
| | | { |
| | | std::vector<CParam> params; |
| | | int nRet = parsingParams(pszData, size, params); |
| | | if (nRet <= 0) return nRet; |
| | | |
| | | char szBuffer[256]; |
| | | for (auto p : params) { |
| | | if(!strOut.empty()) strOut.append(","); |
| | | if (p.getValueType() == PVT_INT) { |
| | | sprintf_s(szBuffer, 256, "%s:%d", p.getName().c_str(), p.getIntValue()); |
| | | } |
| | | else if (p.getValueType() == PVT_DOUBLE) { |
| | | sprintf_s(szBuffer, 256, "%s:%f", p.getName().c_str(), p.getDoubleValue()); |
| | | } |
| | | strOut.append(szBuffer); |
| | | } |
| | | |
| | | return 0; |
| | | }; |
| | | |
| | | void CEquipment::addFacDataReportStep(int dataDev, int writeSignalDev, int port) |
| | | { |
| | | CEqReadStep* pStep = new CEqReadStep(dataDev, 133 * 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*)(__int64)port); |
| | | pStep->setReadContinue(TRUE); |
| | | pStep->setWriteSignalDev(writeSignalDev); |
| | | if (addStep(STEP_ID_FAC_DATA_REPORT, pStep) != 0) { |
| | | delete pStep; |
| | | } |
| | | } |
| | | |
| | | std::vector<SERVO::CSVData>& CEquipment::getSVDatas() |
| | | { |
| | | return m_svDatas; |
| | | } |
| | | } |