| | |
| | | m_listener = { nullptr, nullptr }; |
| | | m_alive = {FALSE, 0, FALSE}; |
| | | m_bCimState = FALSE; |
| | | m_bUpstreamInline = FALSE; |
| | | m_bDownstreamInline = FALSE; |
| | | m_bLocalAlarm = FALSE; |
| | | m_bAutoRecipeChange = FALSE; |
| | | m_bVCREnable[0] = FALSE; |
| | | m_pCclink = nullptr; |
| | | m_nBaseAlarmId = 0; |
| | | InitializeCriticalSection(&m_criticalSection); |
| | | } |
| | | |
| | | CEquipment::~CEquipment() |
| | | { |
| | | for (auto item : m_mapStep) { |
| | | delete item.second; |
| | | } |
| | | m_mapStep.clear(); |
| | | |
| | | for (auto item : m_inputPins) { |
| | | delete item; |
| | | } |
| | | m_inputPins.clear(); |
| | | |
| | | for (auto item : m_outputPins) { |
| | | delete item; |
| | | } |
| | | m_outputPins.clear(); |
| | | |
| | | DeleteCriticalSection(&m_criticalSection); |
| | | } |
| | | |
| | |
| | | m_listener.onCimStateChanged = listener.onCimStateChanged; |
| | | } |
| | | |
| | | void CEquipment::setCcLink(CCCLinkIEControl* pCcLink) |
| | | { |
| | | m_pCclink = pCcLink; |
| | | } |
| | | |
| | | void CEquipment::setBaseAlarmId(int nBaseId) |
| | | { |
| | | m_nBaseAlarmId = nBaseId; |
| | | } |
| | | |
| | | int CEquipment::getBaseAlarmId() |
| | | { |
| | | return m_nBaseAlarmId; |
| | | } |
| | | |
| | | 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")); |
| | | } |
| | | |
| | | std::map<unsigned int, CStep*>& CEquipment::getSteps() |
| | | { |
| | | return m_mapStep; |
| | | } |
| | | |
| | | CStep* CEquipment::getStep(unsigned int addr) |
| | | { |
| | | auto iter = m_mapStep.find(addr); |
| | | if (iter == m_mapStep.end()) return nullptr; |
| | | return iter->second; |
| | | } |
| | | |
| | | CStep* CEquipment::getStepWithName(const char* pszName) |
| | | { |
| | | for (auto item : m_mapStep) { |
| | | if (item.second->getName().compare(pszName) == 0) { |
| | | return item.second; |
| | | } |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | int CEquipment::addStep(unsigned int addr, CStep* pStep) |
| | | { |
| | | auto iter = m_mapStep.find(addr); |
| | | if (iter != m_mapStep.end()) return -1; |
| | | pStep->setEquipment(this); |
| | | pStep->setCcLink(m_pCclink); |
| | | m_mapStep[addr] = pStep; |
| | | return 0; |
| | | } |
| | | |
| | | void CEquipment::init() |
| | | { |
| | | |
| | | initPins(); |
| | | for (auto item : m_mapStep) { |
| | | item.second->init(); |
| | | } |
| | | } |
| | | |
| | | void CEquipment::term() |
| | | { |
| | | |
| | | for (auto item : m_mapStep) { |
| | | item.second->term(); |
| | | } |
| | | } |
| | | |
| | | void CEquipment::setID(int nID) |
| | |
| | | return m_station; |
| | | } |
| | | |
| | | void CEquipment::getAttributeVector(CAttributeVector& attrubutes) |
| | | { |
| | | attrubutes.clear(); |
| | | attrubutes.addAttribute(new CAttribute("Network", |
| | | std::to_string(m_station.nNetNo).c_str(), "")); |
| | | attrubutes.addAttribute(new CAttribute("Station", |
| | | std::to_string(m_station.nStNo).c_str(), "")); |
| | | attrubutes.addAttribute(new CAttribute("ID", |
| | | std::to_string(m_nID).c_str(), "")); |
| | | attrubutes.addAttribute(new CAttribute("Name", |
| | | m_strName.c_str(), "")); |
| | | attrubutes.addAttribute(new CAttribute("Description", |
| | | m_strDescription.c_str(), "")); |
| | | attrubutes.addAttribute(new CAttribute("Alive", |
| | | this->isAlive() ? _T("TRUE") : _T("FALSE"), "")); |
| | | attrubutes.addAttribute(new CAttribute("CIM State", |
| | | m_bCimState ? _T("ON") : _T("OFF"), "")); |
| | | attrubutes.addAttribute(new CAttribute("Upstream", |
| | | m_bUpstreamInline ? _T("Inline") : _T("Offline"), "")); |
| | | attrubutes.addAttribute(new CAttribute("Downstream", |
| | | m_bDownstreamInline ? _T("Inline") : _T("Offline"), "")); |
| | | attrubutes.addAttribute(new CAttribute("Local Alarm", |
| | | m_bLocalAlarm ? _T("TRUE") : _T("FALSE"), "")); |
| | | attrubutes.addAttribute(new CAttribute("Auto Recipe Change", |
| | | m_bAutoRecipeChange ? _T("TRUE") : _T("FALSE"), "")); |
| | | char szTemp[256]; |
| | | for (int i = 0; i < VCR_MAX; i++) { |
| | | sprintf_s(szTemp, 256, "VCR-%d", i + 1); |
| | | attrubutes.addAttribute(new CAttribute(szTemp, |
| | | m_bVCREnable[i] ? _T("Enable") : _T("Disable"), "")); |
| | | } |
| | | |
| | | for (auto item : m_inputPins) { |
| | | attrubutes.addAttribute(new CAttribute(item->getName().c_str(), |
| | | std::to_string((int)item->getType()).c_str(), "")); |
| | | } |
| | | |
| | | for (auto item : m_outputPins) { |
| | | attrubutes.addAttribute(new CAttribute(item->getName().c_str(), |
| | | std::to_string((int)item->getType()).c_str(), "")); |
| | | } |
| | | |
| | | for (auto item : m_panelList) { |
| | | attrubutes.addAttribute(new CAttribute("Panel", |
| | | item->getID().c_str(), "")); |
| | | } |
| | | } |
| | | |
| | | void CEquipment::setReadBitBlock(unsigned int start, unsigned int end) |
| | | { |
| | | m_blockReadBit.type = (unsigned int)DeviceType::LB;; |
| | | m_blockReadBit.type = (unsigned int)DeviceType::B; |
| | | m_blockReadBit.start = start; |
| | | m_blockReadBit.end = end; |
| | | m_blockReadBit.size = (m_blockReadBit.end - m_blockReadBit.start + 1) / 8; |
| | |
| | | |
| | | void CEquipment::onReceiveLBData(const char* pszData, size_t size) |
| | | { |
| | | /* |
| | | TRACE("%s onReceiveLBData: %d bytes\n", m_strName.c_str(), size); |
| | | for (unsigned int i = 0; i < size; i++) { |
| | | if (pszData[i] != 0) |
| | | TRACE("%d[%x]\n", i, pszData[i]); |
| | | } |
| | | |
| | | */ |
| | | |
| | | // 以下解释和处理数据 |
| | | BOOL bFlag; |
| | | int index = 0x340; |
| | | |
| | | |
| | | // alive |
| | | /* |
| | | BOOL bAliveFlag = isBitOn(pszData, size, 0x340); |
| | | if (m_alive.flag != bAliveFlag) { |
| | | m_alive.flag = bAliveFlag; |
| | | bFlag = isBitOn(pszData, size, index); |
| | | if (!equalBool(m_alive.flag, bFlag)) { |
| | | m_alive.flag = bFlag; |
| | | m_alive.count = 0; |
| | | |
| | | // ״̬ |
| | |
| | | } |
| | | } |
| | | } |
| | | */ |
| | | |
| | | // CIM State |
| | | BOOL bCimState = isBitOn(pszData, size, 0x341); |
| | | if ((bCimState && !m_bCimState) || (!bCimState && m_bCimState)) { |
| | | m_bCimState = bCimState; |
| | | bFlag = isBitOn(pszData, size, ++index); |
| | | if (!equalBool(m_bCimState, bFlag)) { |
| | | m_bCimState = bFlag; |
| | | if (m_listener.onCimStateChanged != nullptr) { |
| | | m_listener.onCimStateChanged(this, m_bCimState); |
| | | } |
| | | } |
| | | |
| | | // UpstreamInline |
| | | bFlag = isBitOn(pszData, size, ++index); |
| | | if (!equalBool(m_bUpstreamInline, bFlag)) { |
| | | m_bUpstreamInline = bFlag; |
| | | } |
| | | |
| | | // DownstreamInline |
| | | bFlag = isBitOn(pszData, size, ++index); |
| | | if (!equalBool(m_bDownstreamInline, bFlag)) { |
| | | m_bDownstreamInline = bFlag; |
| | | } |
| | | |
| | | // LocalAlarm |
| | | bFlag = isBitOn(pszData, size, ++index); |
| | | if (!equalBool(m_bLocalAlarm, bFlag)) { |
| | | m_bLocalAlarm = bFlag; |
| | | } |
| | | |
| | | // AutoRecipeChange |
| | | bFlag = isBitOn(pszData, size, ++index); |
| | | if (!equalBool(m_bAutoRecipeChange, bFlag)) { |
| | | m_bAutoRecipeChange = bFlag; |
| | | } |
| | | |
| | | // AutoRecipeChange |
| | | bFlag = isBitOn(pszData, size, ++index); |
| | | if (!equalBool(m_bVCREnable[0], bFlag)) { |
| | | m_bVCREnable[0] = bFlag; |
| | | } |
| | | |
| | | |
| | | // 以下根据信号做流程处理 |
| | | CStep* pStep; |
| | | |
| | | // Equipment Mode Change Report(0x360) |
| | | // Equipment Status Change Report(0x361) |
| | | // Equipment Alarm Change Report(0x362 ~ 0x366) |
| | | for (int i = 0; i < 7; i++) { |
| | | index = 0x360 + i;; |
| | | bFlag = isBitOn(pszData, size, index); |
| | | pStep = getStep(index); |
| | | if (pStep != nullptr) { |
| | | ((CReadStep*)pStep)->onReadSignal(bFlag); |
| | | } |
| | | } |
| | | |
| | | index = 0x350; |
| | | bFlag = isBitOn(pszData, size, index); |
| | | pStep = getStep(index); |
| | | if (pStep != nullptr) { |
| | | ((CWriteStep*)pStep)->onRecvSignal(bFlag); |
| | | } |
| | | } |
| | | |
| | |
| | | return CToolUnits::getBit(pszData[byteIndex], bitIndex); |
| | | } |
| | | |
| | | BOOL CEquipment::equalBool(BOOL b1, BOOL b2) |
| | | { |
| | | return (b1 && b2) || (!b1 && !b2); |
| | | } |
| | | |
| | | BOOL CEquipment::isAlive() |
| | | { |
| | | return m_alive.alive; |
| | | } |
| | | |
| | | BOOL CEquipment::isCimOn() |
| | | { |
| | | return m_bCimState; |
| | | } |
| | | |
| | | BOOL CEquipment::isUpstreamInline() |
| | | { |
| | | return m_bUpstreamInline; |
| | | } |
| | | |
| | | BOOL CEquipment::isDownstreamInline() |
| | | { |
| | | return m_bDownstreamInline; |
| | | } |
| | | |
| | | BOOL CEquipment::isLocalAlarm() |
| | | { |
| | | return m_bLocalAlarm; |
| | | } |
| | | |
| | | BOOL CEquipment::isAutoRecipeChange() |
| | | { |
| | | return m_bAutoRecipeChange; |
| | | } |
| | | |
| | | BOOL CEquipment::isVCREnable(unsigned int index) |
| | | { |
| | | if (index >= VCR_MAX) return FALSE; |
| | | return m_bVCREnable[index]; |
| | | } |
| | | |
| | | CPin* CEquipment::addPin(PinType type, char* pszName) |
| | | { |
| | | // 不允许名字添加重复的pin |
| | | CPin* pPin = getPin(pszName); |
| | | if (pPin != nullptr) return nullptr; |
| | | |
| | | |
| | | // 添加到Pin列表,看是输入pin或输出pin |
| | | if (type == PinType::INPUT) { |
| | | pPin = new CPin(this, type, pszName); |
| | | m_inputPins.push_back(pPin); |
| | | return pPin; |
| | | } |
| | | else if (type == PinType::OUTPUT) { |
| | | pPin = new CPin(this, type, pszName); |
| | | m_outputPins.push_back(pPin); |
| | | return pPin; |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | CPin* CEquipment::getPin(char* pszName) |
| | | { |
| | | for (auto item : m_inputPins) { |
| | | if (item->getName().compare(pszName) == 0) { |
| | | return item; |
| | | } |
| | | } |
| | | |
| | | for (auto item : m_outputPins) { |
| | | if (item->getName().compare(pszName) == 0) { |
| | | return item; |
| | | } |
| | | } |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | std::vector<CPin*>& CEquipment::getInputPins() |
| | | { |
| | | return m_inputPins; |
| | | } |
| | | |
| | | std::vector<CPin*>& CEquipment::getOutputPins() |
| | | { |
| | | return m_outputPins; |
| | | } |
| | | |
| | | int CEquipment::recvIntent(CPin* pPin, CIntent* pIntent) |
| | | { |
| | | ASSERT(pPin); |
| | | CPin* pFromPin = pPin->getConnectedPin(); |
| | | ASSERT(pFromPin); |
| | | CEquipment* pFromEq = pFromPin->getEquipment(); |
| | | ASSERT(pFromEq); |
| | | |
| | | LOGI("<CEquipment><%s-%s>收到来自<%s.%s>的Intent<%d,%s,0x%x>", |
| | | this->getName().c_str(), |
| | | pPin->getName().c_str(), |
| | | pFromEq->getName().c_str(), |
| | | pFromPin->getName().c_str(), |
| | | pIntent->getCode(), |
| | | pIntent->getMsg(), |
| | | pIntent->getContext()); |
| | | |
| | | |
| | | |
| | | // 以下解释处理数据 |
| | | int code = pIntent->getCode(); |
| | | |
| | | |
| | | // 测试 |
| | | if (code == FLOW_TEST) { |
| | | AfxMessageBox(pIntent->getMsg()); |
| | | return FLOW_ACCEPT; |
| | | } |
| | | |
| | | |
| | | // 信号 |
| | | if (code == FLOW_SIGNAL) { |
| | | return FLOW_ACCEPT; |
| | | } |
| | | |
| | | |
| | | // 数据 |
| | | if (code == FLOW_SIGNAL) { |
| | | return FLOW_ACCEPT; |
| | | } |
| | | |
| | | |
| | | // 物料 |
| | | if (code == FLOW_MOVE_MATERIAL) { |
| | | CPanel* pPanel = (CPanel*)pIntent->getContext(); |
| | | ASSERT(pPanel); |
| | | if (!glassWillArrive(pPanel)) { |
| | | return FLOW_REJECT; |
| | | } |
| | | return glassArrived(pPanel); |
| | | } |
| | | |
| | | |
| | | |
| | | return FLOW_ACCEPT; |
| | | } |
| | | |
| | | int CEquipment::outputGlass(int port) |
| | | { |
| | | CPin* pOutPin = nullptr; |
| | | if (port == 0) { |
| | | pOutPin = getPin("Out"); |
| | | if (pOutPin == nullptr) { |
| | | pOutPin = getPin("Out1"); |
| | | } |
| | | } |
| | | else if (port == 1) { |
| | | pOutPin = getPin("Out2"); |
| | | } |
| | | if (pOutPin == nullptr) { |
| | | return -1; |
| | | } |
| | | |
| | | |
| | | // 模拟取出第一张Panel,传送到下一环节 |
| | | Lock(); |
| | | CPanel* pContext = m_panelList.front(); |
| | | pContext->addRef(); |
| | | |
| | | CIntent intent(FLOW_MOVE_MATERIAL, "", pContext); |
| | | int nRet = pOutPin->sendIntent(&intent); |
| | | if (nRet == FLOW_REJECT) { |
| | | LOGE("<CEquipment>对方拒绝接收Intent."); |
| | | } |
| | | else if (nRet == FLOW_ACCEPT) { |
| | | m_panelList.pop_front(); |
| | | pContext->release(); // 添加到列队时addRef, 取出时release |
| | | } |
| | | |
| | | pContext->release(); |
| | | Unlock(); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | BOOL CEquipment::glassWillArrive(CPanel* pPanel) |
| | | { |
| | | return TRUE; |
| | | } |
| | | |
| | | int CEquipment::glassArrived(CPanel* pPanel) |
| | | { |
| | | Lock(); |
| | | pPanel->addRef(); |
| | | m_panelList.push_back(pPanel); |
| | | Unlock(); |
| | | return FLOW_ACCEPT; |
| | | } |
| | | |
| | | void CEquipment::addPanelToList(CPanel* pPanel) |
| | | { |
| | | ASSERT(pPanel); |
| | | |
| | | Lock(); |
| | | pPanel->addRef(); |
| | | m_panelList.push_back(pPanel); |
| | | Unlock(); |
| | | } |
| | | } |