#include "stdafx.h" #include "RemoteEquipment.h" #include #include #include #include #include #include "BEQCommon.h" /* ³¬Ê±Ê±¼ä */ extern int g_nActionTimeout; namespace BEQ { /* socket »º³åÇø´óС */ #define BUFFER_SIZE 1024 CRemoteEquipment::CRemoteEquipment() { m_nPort = 0; m_nLocalPort = 0; m_listener.onConnected = nullptr; m_listener.onConnectFailed = nullptr; m_listener.onDisconnecting = nullptr; m_listener.onDisconnected = nullptr; m_listener.onRead = nullptr; m_listener.onEventUpdate = nullptr; m_hSocket = NULL; m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTED; m_bWorking = FALSE; m_hWSAEvent = nullptr; m_hEventClose = nullptr; m_hEventWrite = nullptr; m_hEventActions = nullptr; m_hEventActionsThreadExit = nullptr; m_hEventTimeoutCheckThreadExit = nullptr; m_pCurrentAction = nullptr; m_data.init(1024); ::InitializeCriticalSection(&m_cs); } CRemoteEquipment::CRemoteEquipment(const char* pszAddr, int port) { m_nPort = 0; m_nLocalPort = 0; m_listener.onConnecting = nullptr; m_listener.onConnected = nullptr; m_listener.onConnectFailed = nullptr; m_listener.onDisconnecting = nullptr; m_listener.onDisconnected = nullptr; m_listener.onRead = nullptr; m_listener.onEventUpdate = nullptr; m_strAddr = pszAddr; m_nPort = port; m_hSocket = NULL; m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTED; m_bWorking = FALSE; m_hWSAEvent = nullptr; m_hEventClose = nullptr; m_hEventWrite = nullptr; m_hEventActions = nullptr; m_hEventActionsThreadExit = nullptr; m_hEventTimeoutCheckThreadExit = nullptr; m_pCurrentAction = nullptr; m_data.init(1024); ::InitializeCriticalSection(&m_cs); m_ullConnectTick = 0; } CRemoteEquipment::~CRemoteEquipment() { close(); for (auto iter = m_units.begin(); iter != m_units.end(); iter++) { delete iter->second; } m_units.clear(); ::DeleteCriticalSection(&m_cs); } void CRemoteEquipment::setRemoteEquipmentListener(RemoteEquipmentListener listener) { m_listener.onConnecting = listener.onConnecting; m_listener.onConnected = listener.onConnected; m_listener.onConnectFailed = listener.onConnectFailed; m_listener.onDisconnecting = listener.onDisconnecting; m_listener.onDisconnected = listener.onDisconnected; m_listener.onRead = listener.onRead; m_listener.onEventUpdate = listener.onEventUpdate; } int CRemoteEquipment::getAddr(char* pszBuffer, int nMaxCount) { return strcpy_s(pszBuffer, nMaxCount, m_strAddr.c_str()); } int CRemoteEquipment::getPort() { return m_nPort; } int CRemoteEquipment::getName(char* pszBuffer, int nMaxCount) { if (!m_strName.empty()) { return strcpy_s(pszBuffer, nMaxCount, m_strName.c_str()); } else { return sprintf_s(pszBuffer, nMaxCount, "%s:%d", m_strAddr.c_str(), m_nPort); } } int CRemoteEquipment::getVersion(char* pszBuffer, int nMaxCount) { return strcpy_s(pszBuffer, nMaxCount, m_strVersion.c_str()); } bool CRemoteEquipment::isConnected() { return m_hSocket != NULL && m_remoteEqNetState == REMOTE_EQ_NET_STATE::CONNECTED; } int CRemoteEquipment::connect() { TRACE("%p, m_remoteEqNetState:%d\n", this, m_remoteEqNetState); if (m_remoteEqNetState == REMOTE_EQ_NET_STATE::CONNECTING || m_remoteEqNetState == REMOTE_EQ_NET_STATE::CONNECTED || m_remoteEqNetState == REMOTE_EQ_NET_STATE::DISCONNECTING) { return -1; } m_remoteEqNetState = REMOTE_EQ_NET_STATE::CONNECTING; if (m_listener.onConnecting != nullptr) { m_listener.onConnecting(this); } // ´ýÔ­Ïß³ÌÍËÁËÏÈ m_bWorking = FALSE; WSASetEvent(m_hWSAEvent); if (m_hEventActions != NULL) { SetEvent(m_hEventActions); } if (m_hEventActionsThreadExit != NULL) { ::WaitForSingleObject(m_hEventActionsThreadExit, INFINITE); } if (m_hEventTimeoutCheckThreadExit != NULL) { ::WaitForSingleObject(m_hEventTimeoutCheckThreadExit, INFINITE); } //×¼±¸·þÎñÆ÷µÄÐÅÏ¢£¬ÕâÀïÐèÒªÖ¸¶¨·þÎñÆ÷µÄµØÖ· sockaddr_in addr; struct in_addr dst; if (InetPton(AF_INET, m_strAddr.c_str(), &dst) != 1) { return -1; } addr.sin_family = AF_INET; addr.sin_addr = dst; addr.sin_port = htons(m_nPort); //¸Ä±ä¶Ë¿ÚºÅµÄÊý¾Ý¸ñʽ // Èç¹ûÔ­À´´ò¿ªÕâÌ×½Ó×ÖÏÈ¹Ø±Õ if (m_hSocket != NULL) { closesocket(m_hSocket); m_hSocket = NULL; } // ´´½¨ÐµÄÌ×½Ó×Ö if (m_hSocket == NULL) { m_hSocket = socket(AF_INET, SOCK_STREAM, 0); ASSERT(m_hSocket != NULL); initClient(); } if (m_hEventClose == NULL) { m_hEventClose = ::CreateEvent(NULL, TRUE, FALSE, NULL); } ResetEvent(m_hEventClose); if (m_hEventActions == NULL) { m_hEventActions = ::CreateEvent(NULL, TRUE, FALSE, NULL); } ResetEvent(m_hEventActions); if (m_hEventActionsThreadExit == NULL) { m_hEventActionsThreadExit = ::CreateEvent(NULL, TRUE, FALSE, NULL); } ResetEvent(m_hEventActionsThreadExit); if (m_hEventTimeoutCheckThreadExit == NULL) { m_hEventTimeoutCheckThreadExit = ::CreateEvent(NULL, TRUE, FALSE, NULL); } ResetEvent(m_hEventTimeoutCheckThreadExit); // Ö÷¶¯Á¬½Ó·þÎñÆ÷£¬¸Ã¹ý³Ì½«µÈ´ýÒ»¶¨Ê±¼ä if (SOCKET_ERROR == ::connect(m_hSocket, (LPSOCKADDR)&addr, sizeof(addr))) { if (WSAGetLastError() != WSAEWOULDBLOCK) return -2; } return 0; } int CRemoteEquipment::close() { m_bWorking = FALSE; WSASetEvent(m_hWSAEvent); if (m_hEventActions != NULL) { SetEvent(m_hEventActions); } lock(); if (m_hSocket != NULL) { m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTING; if (m_listener.onDisconnecting != nullptr) { m_listener.onDisconnecting(this); } shutdown(m_hSocket, SD_BOTH); closesocket(m_hSocket); m_hSocket = NULL; unlock(); if (m_hEventClose != NULL) { ::WaitForSingleObject(m_hEventClose, INFINITE); } if (m_hEventActionsThreadExit != NULL) { ::WaitForSingleObject(m_hEventActionsThreadExit, INFINITE); } if (m_hEventTimeoutCheckThreadExit != NULL) { ::WaitForSingleObject(m_hEventTimeoutCheckThreadExit, INFINITE); } m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTED; if (m_listener.onDisconnected != nullptr) { m_listener.onDisconnected(this); } } else { unlock(); } return 0; } int CRemoteEquipment::reqGetAction(int type, const char* pszCommand, const char* pszUnitName, const char* pszParams) { std::string strRawText = std::string(pszCommand) + "@EQID=" + m_strName; if (pszUnitName) { strRawText += ("/UNIT=" + std::string(pszUnitName)); } if (pszParams) { strRawText += pszParams; } strRawText += "#"; CAction* pAction = new CAction(type); ASSERT(pAction); pAction->setRawString(strRawText.c_str()); lock(); m_actions.push_back(pAction); unlock(); SetEvent(m_hEventActions); return pAction->getId(); } int CRemoteEquipment::reqGetName() { return reqGetAction(ACTION_GETNAME, CMD_GET_EQID_REQ); } int CRemoteEquipment::reqGetVersion() { return reqGetAction(ACTION_GETVERSION, CMD_GET_VERSION_REQ); } int CRemoteEquipment::reqGetState(const char* pszUnitName) { return reqGetAction(ACTION_GETDEVICESTATE, CMD_GET_STATE_REQ, pszUnitName); } int CRemoteEquipment::reqGetDoorState(const char* pszUnitName) { return reqGetAction(ACTION_GETDOORSTATE, CMD_GET_DOOR_REQ, pszUnitName); } int CRemoteEquipment::reqGetAlarmInfo(const char* pszUnitName) { return reqGetAction(ACTION_GETALARMINFO, CMD_GET_ERROR_REQ, pszUnitName); } int CRemoteEquipment::reqGetStep(const char* pszUnitName) { return reqGetAction(ACTION_GETSTEP, CMD_GET_STEP_REQ, pszUnitName); } int CRemoteEquipment::reqGetData(const char* pszUnitName) { return reqGetAction(ACTION_GETDATA, CMD_GET_DATA_REQ, pszUnitName); } int CRemoteEquipment::reqRecipeList(const char* pszUnitName) { return reqGetAction(ACTION_GETRECIPELIST, CMD_GET_RECIPE_LIST_REQ, pszUnitName); } int CRemoteEquipment::reqRunRecipe(const char* pszUnitName, int nRecipeId, const char* pszRecipeName) { std::string strParams = "/RECIPEID=" + std::to_string(nRecipeId) + "/RECIPENAME=" + pszRecipeName; return reqGetAction(ACTION_RUNRECIPE, CMD_RUN_RECIPE_REQ, pszUnitName, strParams.c_str()); } IUnit* CRemoteEquipment::addUnit(const char* pszName, int nDoorCount) { auto iter = m_units.find(pszName); if (iter != m_units.end()) { return (IUnit*)iter->second; } CUnit* pUnit = new CUnit(pszName); m_units[pszName] = pUnit; pUnit->setDoorCount(nDoorCount); UnitListener listener; listener.onStateChanged = [&](void* pUnit, EQ_STATE nStete) -> void { TRACE("onStateChanged...\n"); }; listener.onDoorStateChanged = [&](void* pUnit, int stete) -> void { TRACE("onDoorStateChanged...\n"); }; listener.onAlarm = [&](void* pUnit, int code, int level, const char* pszText) -> void { TRACE("onAlarm...\n"); }; listener.onRemoveAlarm = [&](void* pUnit, int code, int level, const char* pszText) -> void { TRACE("onRemoveAlarm...\n"); }; listener.onStepChanged = [&](void* pUnit, STEP_STATE) -> void { TRACE("onStepChanged...\n"); }; listener.onDataChanged = [&](void* pUnit, unsigned long long time) -> void { TRACE("onDataChanged...\n"); }; listener.onReqLoad = [&](void* pUnit, int layer) -> void { TRACE("onReqLoad...\n"); }; listener.onReqUnload = [&](void* pUnit, int layer) -> void { TRACE("onReqUnload...\n"); }; pUnit->setListener(listener); return (IUnit*)pUnit; } IUnit* CRemoteEquipment::getUnit(const char* pszName) { auto iter = m_units.find(pszName); if (iter != m_units.end()) { return (IUnit*)iter->second; } return nullptr; } const char** CRemoteEquipment::getAllUnitNames() { const int maxUnits = 128; static const char* unitNames[maxUnits]; int index = 0; for (const auto& pair : m_units) { if (index >= maxUnits) break; unitNames[index++] = pair.first.c_str(); } return unitNames; } int CRemoteEquipment::getUnitCount() const { return m_units.size(); } ULONGLONG CRemoteEquipment::getConnectTick() { return m_ullConnectTick; } BOOL CRemoteEquipment::initClient() { // Èç¹ûÖ¸¶¨Á˱¾µØ¶Ë¿Ú(port != 0), ÔòÒª°ó¶¨Ö¸¶¨¶Ë¿Ú // °ó¶¨Ò»¸öÌ×½Ó×Öµ½±¾»úµÄµØÖ· ASSERT(m_hSocket); // ref https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse int reuse = 1; setsockopt(m_hSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)); if (m_nLocalPort != 0) { sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.S_un.S_addr = INADDR_ANY; addr.sin_port = htons(m_nLocalPort); bind(m_hSocket, (LPSOCKADDR)&addr, sizeof(addr)); } // ²ÉÓÃʼþÑ¡ÔñÄ£ÐÍWSAEventSelect m_hWSAEvent = WSACreateEvent(); WSAEventSelect(m_hSocket, m_hWSAEvent, FD_CONNECT | FD_READ | FD_CLOSE | FD_WRITE); m_bWorking = TRUE; CWinThread* pThread = AfxBeginThread(&CRemoteEquipment::WorkerThreadFunction, (LPVOID)this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); if (pThread) { pThread->ResumeThread(); } pThread = AfxBeginThread(&CRemoteEquipment::TimeoutCheckThreadFunction, (LPVOID)this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); if (pThread) { pThread->ResumeThread(); } pThread = AfxBeginThread(&CRemoteEquipment::ActionsThreadFunction, (LPVOID)this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED); if (pThread) { pThread->ResumeThread(); } return TRUE; } UINT CRemoteEquipment::WorkerThreadFunction(LPVOID lpvData) { CRemoteEquipment *pRemoteEquipment = (CRemoteEquipment *)lpvData; return pRemoteEquipment->WorkerThreadFunctionInner(); } UINT CRemoteEquipment::WorkerThreadFunctionInner() { int nThreadID, ret, index; WSANETWORKEVENTS networkEvents; Sleep(100); // ±ØÐëµÈ´ý,ʹCreateChann...·µ»Ø nThreadID = 0; char szRecvBuffer[BUFFER_SIZE]; while (m_bWorking) { // ¼ì²âsocketÊÇ·ñÓÐЧ lock(); if (m_hSocket == NULL) { unlock(); break; } unlock(); // µÈ´ýÍøÂçʼþ ret = WSAWaitForMultipleEvents(1, &m_hWSAEvent, FALSE, 1000, FALSE); if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT) { continue; } index = ret - WSA_WAIT_EVENT_0; WSAEnumNetworkEvents(m_hSocket, m_hWSAEvent, &networkEvents); // ÓÐÊý¾Ýµ½´ï if (networkEvents.lNetworkEvents & FD_READ) { int nRet = recv(m_hSocket, (char*)&szRecvBuffer, BUFFER_SIZE, 0); if (nRet != SOCKET_ERROR) { // ½âÊÍÊý¾Ý int nDecodeRet = decode((char*)&szRecvBuffer, nRet); if (m_listener.onRead != nullptr) { m_listener.onRead(this, szRecvBuffer, nRet); } } } // Á´½Ó¹Ø±Õ if (networkEvents.lNetworkEvents & FD_CLOSE) { TRACE("Á´½Ó¹Ø±Õ\n"); m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTED; if (m_listener.onDisconnected != nullptr) { m_listener.onDisconnected(this); } break; } // Á´½Ó½á¹û if (networkEvents.lNetworkEvents & FD_CONNECT) { TRACE("Á´½Ó½á¹û\n"); m_ullConnectTick = GetTickCount64(); ResetEvent(m_hEventClose); if (networkEvents.iErrorCode[FD_CONNECT_BIT] == 0) { reqGetName(); } else { m_remoteEqNetState = REMOTE_EQ_NET_STATE::DISCONNECTED; if (m_listener.onConnectFailed != nullptr) { m_listener.onConnectFailed(this, networkEvents.iErrorCode[FD_CONNECT_BIT]); } m_bWorking = false; break; } } if (networkEvents.lNetworkEvents & FD_WRITE) { if (m_hEventWrite != NULL) { SetEvent(m_hEventWrite); } } } // ʹm_hEventClose ÊÜÐÅ, Closeº¯Êý·µ»Ø if (m_hEventClose != NULL) { TRACE("m_hEventClose ÊÜÐÅ\n"); ::SetEvent(m_hEventClose); } return 0; } UINT CRemoteEquipment::ActionsThreadFunction(LPVOID lpvData) { CRemoteEquipment *pRemoteEquipment = (CRemoteEquipment *)lpvData; return pRemoteEquipment->ActionsThreadFunctionInner(); } UINT CRemoteEquipment::ActionsThreadFunctionInner() { ULONGLONG lastTick = 0; DWORD dwWait = INFINITE; while (m_bWorking) { DWORD dwRet = WaitForSingleObject(m_hEventActions, dwWait); ResetEvent(m_hEventActions); if (!m_bWorking) { break; } lock(); if (m_pCurrentAction == NULL && m_actions.size() > 0) { CAction* pAction = m_actions.front(); m_pCurrentAction = pAction; m_actions.pop_front(); // ·¢ËÍÊý¾Ý char* pRawData = NULL; int size, validLen; m_pCurrentAction->getRawData(pRawData, size, validLen); send(m_hSocket, pRawData, validLen, 0); } unlock(); } TRACE("ActionsThreadFunctionInner exit\n"); SetEvent(m_hEventActionsThreadExit); return 0; } UINT CRemoteEquipment::TimeoutCheckThreadFunction(LPVOID lpvData) { CRemoteEquipment *pRemoteEquipment = (CRemoteEquipment *)lpvData; return pRemoteEquipment->TimeoutCheckThreadFunctionInner(); } UINT CRemoteEquipment::TimeoutCheckThreadFunctionInner() { BOOL bMatchRemoteEq = TRUE; while (m_bWorking) { Sleep(1000); if (!m_bWorking) { break; } lock(); if (m_pCurrentAction != NULL) { int nTime = m_pCurrentAction->timeIncrease(1000); if (nTime > g_nActionTimeout) { CurrentActionTimeout(); if (m_pCurrentAction->getType() == ACTION_GETNAME) { bMatchRemoteEq = FALSE; } delete m_pCurrentAction; m_pCurrentAction = NULL; SetEvent(m_hEventActions); if (!bMatchRemoteEq) { unlock(); break; } } } unlock(); } SetEvent(m_hEventTimeoutCheckThreadExit); if (!bMatchRemoteEq) { this->close(); if (m_listener.onConnectFailed != nullptr) { m_listener.onConnectFailed(this, -1); } } TRACE("TimeoutCheckThreadFunctionInner exit\n"); return 0; } void CRemoteEquipment::CurrentActionTimeout() { TRACE("Packer CurrentActionTimeout %d", g_nActionTimeout); } void CRemoteEquipment::splitCString(const CString& strText, TCHAR delimiter, std::function callback) { // ͨÓÃ×Ö·û´®ÇиÊý£¬Ö§³Ö»Øµ÷º¯Êý´¦Àíÿ´Î½âÎöºóµÄ½á¹û CString strGet; int index = 0; while (AfxExtractSubString(strGet, strText.GetString(), index, delimiter)) { // Èç¹ûÌṩÁ˻ص÷º¯Êý£¬ÔòÖ´Ðлص÷£¬´«µÝµ±Ç°µÄ×Ö·û´®ºÍË÷Òý if (callback) { callback(strGet, index); } ++index; } } void CRemoteEquipment::notifyEventUpdate(REMOTE_EQ_EVENT eventCode, CUnit* pUnit) { if (m_listener.onEventUpdate != nullptr) { m_listener.onEventUpdate(this, pUnit, eventCode); } } void CRemoteEquipment::processDoorState(const CString& strPart, int index, int& doorState) { if (strPart.CompareNoCase(_T("OPEN")) == 0) { doorState |= (0x01 << index); } } void CRemoteEquipment::updateDoorState(const CString& strText, int& doorState, CUnit* pUnit) { // ²¶»ñthisÖ¸Õ룬ʹµÃLambda¿ÉÒÔ·ÃÎÊÀàµÄ³ÉÔ±º¯Êý»ò±äÁ¿ splitCString(strText, ',', [this, &doorState](const CString& part, int index) { processDoorState(part, index, doorState); }); pUnit->setDoorState(doorState); } void CRemoteEquipment::parseAlarm(const CString& strText, CUnit* pUnit) { int alarmCode = -1; int alarmLevel = -1; CString alarmMessage; if (0 == _ttoi(strText)) { pUnit->setAlarm(0, 0, ""); return; } splitCString(strText, ',', [&alarmCode, &alarmLevel, &alarmMessage](const CString& part, int index) { // ¸ù¾Ýµ±Ç°Ë÷Òý´¦Àí²»Í¬µÄ±¨¾¯ÐÅÏ¢ switch (index) { case 0: // ±¨¾¯´úÂë alarmCode = _ttoi(part); break; case 1: // ±¨¾¯¼¶±ð alarmLevel = _ttoi(part); break; case 2: // ±¨¾¯ÏûÏ¢ alarmMessage = part; break; default: break; } }); // È·±£½âÎöµ½3¸ö×Ó×Ö·û´®£¬²¢ÉèÖñ¨¾¯ÐÅÏ¢ if (alarmCode != -1 && alarmLevel != -1 && !alarmMessage.IsEmpty()) { pUnit->setAlarm(alarmCode, alarmLevel, alarmMessage.GetString()); } } void CRemoteEquipment::handleState(const std::map& params, CUnit* pUnit) { auto iter = params.find(PARAM_STATE); if (iter != params.end()) { std::string strState(iter->second); pUnit->setStateFromString(strState); notifyEventUpdate(REMOTE_EQ_EVENT::DEVICE_STATUS_CHANGED, pUnit); } } void CRemoteEquipment::handleDoorState(const std::map& params, CUnit* pUnit) { auto iter = params.find(PARAM_DOOR); if (iter != params.end()) { CString strText = iter->second.c_str(); int doorState = 0; updateDoorState(strText, doorState, pUnit); notifyEventUpdate(REMOTE_EQ_EVENT::DOOR_STATUS_CHANGED, pUnit); } } void CRemoteEquipment::handleAlarmInfo(const std::map& params, CUnit* pUnit) { auto iter = params.find(PARAM_CODE); if (iter != params.end()) { CString strText = iter->second.c_str(); parseAlarm(strText, pUnit); notifyEventUpdate(REMOTE_EQ_EVENT::ALARM_INFO_CHANGED, pUnit); } } void CRemoteEquipment::handleStep(const std::map& params, CUnit* pUnit) { auto materialIter = params.find(PARAM_MATERIAL_ID); auto stepIter = params.find(PARAM_STEP); if (stepIter != params.end()) { auto pvIter = params.find(PARAM_PVTIME); auto svIter = params.find(PARAM_SVTIME); const std::string& strStep = stepIter->second; const std::string& strMaterialId = materialIter != params.end() ? materialIter->second : ""; int iSVTime = svIter != params.end() ? _ttoi(svIter->second.c_str()) : 0; int iPVTime = pvIter != params.end() ? _ttoi(pvIter->second.c_str()) : 0; handleMachineProcess(strMaterialId, strStep, pUnit, iSVTime, iPVTime); notifyEventUpdate(REMOTE_EQ_EVENT::PRODUCTION_PROCESS_CHANGED, pUnit); } } void CRemoteEquipment::handleData(const std::map& params, CUnit* pUnit) { auto retIter = params.find(PARAM_RESULT); auto texIter = params.find(PARAM_TEX); if ((retIter != params.end() && retIter->second.compare("FAIL")) || (texIter != params.end() && texIter->second.compare("NO DATA"))) { // »ñÈ¡Êý¾Ýʧ°Ü»òûÓÐÊý¾Ý£¬²»×ö´¦Àí } else { auto preIter = params.find(PARAM_PRE); auto airIter = params.find(PARAM_AIR); auto tmpIter = params.find(PARAM_TMP); auto timeIter = params.find(PARAM_TIME); if (timeIter != params.end() && preIter != params.end() && airIter != params.end() && tmpIter != params.end()) { uint64_t timestamp = pUnit->stringToTimeStamp(timeIter->second); pUnit->setDataTimeAndResetData(timestamp); pUnit->addData("PRE", preIter->second.c_str(), true); pUnit->addData("AIR", airIter->second.c_str(), true); pUnit->addData("TMP", tmpIter->second.c_str(), true); notifyEventUpdate(REMOTE_EQ_EVENT::SERSOR_DATA_CHANGED, pUnit); } } } void CRemoteEquipment::handleRecipeList(const std::map& params, CUnit* pUnit) { auto retIter = params.find(PARAM_RESULT); auto texIter = params.find(PARAM_TEX); if ((retIter != params.end() && retIter->second.compare("FAIL")) || (texIter != params.end() && texIter->second.compare("NO RECIPE"))) { // »ñÈ¡Å䷽ʧ°Ü»òûÓÐÅä·½£¬²»×ö´¦Àí } else { auto recipeIter = params.find(PARAM_RECIPE_LIST); if (recipeIter != params.end()) { // ½âÎöÅä·½Áбí CString strRecipeList = recipeIter->second.c_str(); splitCString(strRecipeList, ',', [pUnit](const CString& part, int index) { static int iRecipeid = -1; if ((index + 1) % 2 == 0) { pUnit->addRecipe(iRecipeid, part, true); } else { iRecipeid = _ttoi(part); } }); notifyEventUpdate(REMOTE_EQ_EVENT::RECIPE_LIST_CHANGED, pUnit); } } } void CRemoteEquipment::handleIdle(CUnit* pUnit) { pUnit->stepIdle(); } void CRemoteEquipment::handleMaterialReceived(const std::string& strMaterialId, CUnit* pUnit) { pUnit->stepMaterialReceived(strMaterialId.c_str()); } void CRemoteEquipment::handleMaterialRemoved(const std::string& strMaterialId, CUnit* pUnit) { pUnit->stepMaterialRemoved(strMaterialId.c_str()); } void CRemoteEquipment::handleProcessingStarted(const std::string& strMaterialId, CUnit* pUnit) { pUnit->stepProcessingStarted(strMaterialId.c_str()); } void CRemoteEquipment::handleProcessing(const std::string& strMaterialId, CUnit* pUnit, int svTime, int pvTime) { pUnit->stepProcessing(strMaterialId.c_str(), svTime, pvTime); } void CRemoteEquipment::handleProcessingCompleted(const std::string& strMaterialId, CUnit* pUnit) { pUnit->stepProcessingCompleted(strMaterialId.c_str()); } void CRemoteEquipment::handleMachineProcess(const std::string& strMaterialId, const std::string& strStep, CUnit* pUnit, int svTime, int pvTime) { // Ó³Éä²½Öèµ½´¦Àíº¯Êý static const std::unordered_map> stepHandlers = { {"IDLE", [this](const std::string&, CUnit* pUnit, int, int) { handleIdle(pUnit); }}, {"MATERIAL_RECEIVED", [this](const std::string& strMaterialId, CUnit* pUnit, int, int) { handleMaterialReceived(strMaterialId, pUnit); }}, {"MATERIAL_REMOVED", [this](const std::string& strMaterialId, CUnit* pUnit, int, int) { handleMaterialRemoved(strMaterialId, pUnit); }}, {"PROCESSING_STARTED", [this](const std::string& strMaterialId, CUnit* pUnit, int, int) { handleProcessingStarted(strMaterialId, pUnit); }}, {"PROCESSING_COMPLETED", [this](const std::string& strMaterialId, CUnit* pUnit, int, int) { handleProcessingCompleted(strMaterialId, pUnit); }}, {"PROCESSING", [this](const std::string& strMaterialId, CUnit* pUnit, int svTime, int pvTime) { handleProcessing(strMaterialId, pUnit, svTime, pvTime); }} }; // ²éÕÒ´¦Àíº¯Êý²¢Ö´ÐÐ auto handler = stepHandlers.find(strStep); if (handler != stepHandlers.end()) { handler->second(strMaterialId, pUnit, svTime, pvTime); // ´«µÝ svTime ºÍ pvTime } } int CRemoteEquipment::decode(char* pszBuffer, int nBufferSize) { std::string txt = std::string(pszBuffer, nBufferSize); TRACE("decode:%s\n", txt.c_str()); int nRet = REPLY_NOERROR; int iParam = 0; CString strParam, strCmd, strBody; std::map params; lock(); if (-1 == m_data.append(pszBuffer, nBufferSize)) { nRet = REPLY_MEMROY_ERROR; goto CURACTION; } // ÔÚδÕÒµ½@·û֮ǰ£¬ËùÓеÄ×Öĸ±ØÐëÊÇ 'A' ~ 'Z' »ò '_' int nCmdEnd = -1; BOOL bInvalid = false; for (int i = 0; i < m_data.m_nDataLen; i++) { if ((char)'@' == m_data.m_pBuffer[i]) { nCmdEnd = i; break; } if (!(((char)'A' <= m_data.m_pBuffer[i] && m_data.m_pBuffer[i] <= (char)'Z') || (char)'_' == m_data.m_pBuffer[i])) { bInvalid = true; break; } } if (bInvalid) { m_data.clear(); nRet = REPLY_PACKET_ERROR; goto CURACTION; } if (nCmdEnd <= 0) { nRet = REPLY_PACKET_ERROR; goto CURACTION; } // ²éÕÒÖÕÖ¹·û int nPacketEnd = -1; bInvalid = false; for (int i = nCmdEnd; i < m_data.m_nDataLen; i++) { if ((char)'#' == m_data.m_pBuffer[i]) { nPacketEnd = i; break; } /* if (!((char)32 <= m_data.m_pBuffer[i] && m_data.m_pBuffer[i] <= (char)127)) { bInvalid = true; break; } */ } if (bInvalid) { m_data.clear(); nRet = REPLY_PACKET_ERROR; goto CURACTION; } if (nPacketEnd <= nCmdEnd) { nRet = REPLY_PACKET_NOT_END; goto CURACTION; } // µÃµ½ÃüÁÏûÏ¢Ìå // ÏûÏ¢Ìå·Ö½âΪ²ÎÊýÁбí strCmd = CString(m_data.m_pBuffer, nCmdEnd); strBody = CString(&m_data.m_pBuffer[nCmdEnd + 1], nPacketEnd - nCmdEnd - 1); do { if (!AfxExtractSubString(strParam, (LPCTSTR)strBody, iParam, '/')) break; int n = strParam.Find("="); if (n > 0) { std::string strName = (LPTSTR)(LPCTSTR)strParam.Left(n); std::string strValue = (LPTSTR)(LPCTSTR)strParam.Right(strParam.GetLength() - n - 1); params[strName] = strValue; } iParam++; } while (true); CURACTION: m_data.clear(); // »ñÈ¡É豸µ¥ÔªÖ¸Õë CUnit* pUnit = nullptr; auto unitParamIter = params.find(PARAM_UNIT); if (unitParamIter != params.end()) { auto unitMapIter = m_units.find(unitParamIter->second); if (unitMapIter != m_units.end() && unitMapIter->second != nullptr) { pUnit = unitMapIter->second; } } if (m_pCurrentAction != NULL) { m_pCurrentAction->setReplyCode(nRet); if (m_pCurrentAction->getType() == ACTION_GETNAME && strCmd.Compare(CMD_GET_EQID_REP) == 0) { auto iter = params.find(PARAM_EQID); if (iter != params.end()) { m_strName = iter->second; m_remoteEqNetState = REMOTE_EQ_NET_STATE::CONNECTED; if (m_listener.onConnected != nullptr) { m_listener.onConnected(this); } // test reqGetVersion(); reqGetState("UNITA"); reqGetDoorState("UNITA"); } } else if (m_pCurrentAction->getType() == ACTION_GETVERSION && strCmd.Compare(CMD_GET_VERSION_REP) == 0) { auto iter = params.find(PARAM_VERSION); if (iter != params.end()) { m_strVersion = iter->second; } } else if (m_pCurrentAction->getType() == ACTION_GETDEVICESTATE && strCmd.Compare(CMD_GET_STATE_REP) == 0 && pUnit != nullptr) { handleState(params, pUnit); } else if (m_pCurrentAction->getType() == ACTION_GETDOORSTATE && strCmd.Compare(CMD_GET_DOOR_REP) == 0 && pUnit != nullptr) { handleDoorState(params, pUnit); } else if (m_pCurrentAction->getType() == ACTION_GETALARMINFO && strCmd.Compare(CMD_GET_ERROR_REP) == 0 && pUnit != nullptr) { handleAlarmInfo(params, pUnit); } else if (m_pCurrentAction->getType() == ACTION_GETSTEP && strCmd.Compare(CMD_GET_STEP_REP) == 0 && pUnit != nullptr) { handleStep(params, pUnit); } else if (m_pCurrentAction->getType() == ACTION_GETDATA && strCmd.Compare(CMD_GET_DATA_REP) == 0 && pUnit != nullptr) { handleData(params, pUnit); } else if (m_pCurrentAction->getType() == ACTION_GETRECIPELIST && strCmd.Compare(CMD_GET_RECIPE_LIST_REP) == 0 && pUnit != nullptr) { handleRecipeList(params, pUnit); } else if (m_pCurrentAction->getType() == ACTION_RUNRECIPE && strCmd.Compare(CMD_RUN_RECIPE_REP) == 0 && pUnit != nullptr) { AfxMessageBox("Åä·½Ö´ÐÐÖÐ... ..."); } else { // ÆäËûÃüÁî } // °ü³ö´í£¬ÇÒ²»ÐèҪƴÏÂÒ»°ü if (nRet != REPLY_PACKET_NOT_END) { delete m_pCurrentAction; m_pCurrentAction = NULL; SetEvent(m_hEventActions); } } else { if (pUnit != nullptr) { if (strCmd.Compare(AS_MC_STATE_REP) == 0) { // »ñÈ¡»úÆ÷״̬ handleState(params, pUnit); } else if (strCmd.Compare(AS_GET_DOOR_REP) == 0) { // »ñÈ¡ÃÅ״̬ handleDoorState(params, pUnit); } else if (strCmd.Compare(AS_SEND_ERROR_REP) == 0) { // »ñÈ¡´íÎóÂë handleAlarmInfo(params, pUnit); } else if (strCmd.Compare(AS_REMOVE_ERROR_REP) == 0) { // ½â³ý¸æ¾¯ pUnit->setAlarm(0, 0, ""); notifyEventUpdate(REMOTE_EQ_EVENT::REMOVE_ALARM_INFO, pUnit); } else if (strCmd.Compare(AS_SEND_STEP_REP) == 0) { // ´¦Àí»úÆ÷ÖÆ³Ì handleStep(params, pUnit); } else if (strCmd.Compare(AS_MC_INFO_REP) == 0) { // »ñÈ¡×îÐÂÊý¾Ý£¬´«¸ÐÆ÷£¨Î¶ȡ¢Ñ¹Á¦µÈ£© handleData(params, pUnit); } else if (strCmd.Compare(AS_SEND_EVENT_REP) == 0) { // ´¦ÀíÉϱ¨Ê¼þ notifyEventUpdate(REMOTE_EQ_EVENT::LOAD_EVENT_CHANGED, pUnit); } } } unlock(); return 0; } }