| | |
| | | |
| | | { |
| | | // 请æ±é
æ¹åæ° |
| | | //CEqWriteStep* pStep = new CEqWriteStep(); |
| | | //pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ); |
| | | //pStep->setWriteSignalDev(0x967); |
| | | //pStep->setDataDev(0x379b); |
| | | //if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) { |
| | | // delete pStep; |
| | | //} |
| | | CEqWriteStep* pStep = new CEqWriteStep(); |
| | | pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ); |
| | | pStep->setWriteSignalDev(0x967); |
| | | pStep->setDataDev(0x24fb); |
| | | if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) { |
| | | delete pStep; |
| | | } |
| | | } |
| | | |
| | | { |
| | | // recipe parameter report |
| | | //CEqReadStep* pStep = new CEqReadStep(0x1aa54, 257 * 2, |
| | | // [&](void* pFrom, int code, const char* pszData, size_t size) -> int { |
| | | // if (code == ROK && pszData != nullptr && size > 0) { |
| | | // // æ¤å¤è§£éé
æ¹æ°æ® |
| | | // short ret = decodeRecipeParameterReport(pszData, size); |
| | | // pStep->setReturnCode(ret); |
| | | // } |
| | | // pStep->setReturnCode(MRLRC_OK); |
| | | // return -1; |
| | | // }); |
| | | //pStep->setName(STEP_EQ_RECIPE_PARAMETER); |
| | | //pStep->setWriteSignalDev(0x94c); |
| | | //pStep->setReturnDev(m_nIndex == 0 ? 0x126c : 0x1bbc); |
| | | //if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) { |
| | | // delete pStep; |
| | | //} |
| | | CEqReadStep* pStep = new CEqReadStep(0x12a54, 257 * 2, |
| | | [&](void* pFrom, int code, const char* pszData, size_t size) -> int { |
| | | CEqReadStep* pTmpStep = (CEqReadStep*)pFrom; |
| | | if (code == ROK && pszData != nullptr && size > 0) { |
| | | // æ¤å¤è§£éé
æ¹æ°æ® |
| | | short ret = decodeRecipeParameterReport(pszData, size); |
| | | pTmpStep->setReturnCode(ret); |
| | | } |
| | | pTmpStep->setReturnCode(MRLRC_OK); |
| | | return -1; |
| | | }); |
| | | pStep->setName(STEP_EQ_RECIPE_PARAMETER); |
| | | pStep->setWriteSignalDev(0x94c); |
| | | pStep->setReturnDev(0x250c); |
| | | if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) { |
| | | delete pStep; |
| | | } |
| | | } |
| | | |
| | | // 使ç¨CEqReadStepæ¿æ¢CEqJobEventStep |
| | |
| | | if (pGlass == nullptr) return false; |
| | | return pGlass->isProcessed(m_nID, getSlotUnit(slot)); |
| | | } |
| | | |
| | | int CBakeCooling::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params) |
| | | { |
| | | ASSERT(pszData); |
| | | if (size < 250) return 0; |
| | | int i = 0, v; |
| | | |
| | | |
| | | // 1.A_è
çç¤æ¶é´ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("A_è
çç¤æ¶é´", "", "", v * 0.01f)); |
| | | i += 2; |
| | | |
| | | // 2.A_è
å·å´æ¶é´ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("A_è
å·å´æ¶é´", "", "", v * 0.01f)); |
| | | i += 2; |
| | | |
| | | // 3.B_è
çç¤æ¶é´ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("B_è
çç¤æ¶é´", "", "", v * 0.01f)); |
| | | i += 2; |
| | | |
| | | // 4.BB_è
å·å´æ¶é´ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("B_è
å·å´æ¶é´", "", "", v * 0.01f)); |
| | | i += 2; |
| | | |
| | | // 5.A_çç¤æ¸©åº¦è®¾å® |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("A_çç¤æ¸©åº¦è®¾å®", "", "", v * 0.1f)); |
| | | i += 2; |
| | | |
| | | // 6.B_çç¤æ¸©åº¦è®¾å® |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("B_çç¤æ¸©åº¦è®¾å®", "", "", v * 0.1f)); |
| | | i += 2; |
| | | |
| | | |
| | | return (int)params.size(); |
| | | } |
| | | |
| | | } |
| | |
| | | virtual int getIndexerOperationModeBaseValue(); |
| | | virtual short getSlotUnit(short slotNo) { return slotNo % 2 == 1 ? 0 : 1; }; |
| | | virtual bool isSlotProcessed(int slot); |
| | | virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms); |
| | | }; |
| | | } |
| | | |
| | |
| | | { |
| | | // recipe parameter report |
| | | CEqReadStep* pStep = new CEqReadStep(m_nIndex == 0 ? 0xaa54 : 0xea54, 257 * 2, |
| | | [&](void* pFrom, int code, const char* pszData, size_t size) -> int { |
| | | [&, pStep](void* pFrom, int code, const char* pszData, size_t size) -> int { |
| | | CEqReadStep* pTmpStep = (CEqReadStep*)pFrom; |
| | | short ret = MRLRC_OK; |
| | | if (code == ROK && pszData != nullptr && size > 0) { |
| | | // æ¤å¤è§£éé
æ¹æ°æ® |
| | | short ret = decodeRecipeParameterReport(pszData, size); |
| | | pStep->setReturnCode(ret); |
| | | ret = decodeRecipeParameterReport(pszData, size); |
| | | } |
| | | pStep->setReturnCode(MRLRC_OK); |
| | | pTmpStep->setReturnCode(ret); |
| | | return -1; |
| | | }); |
| | | pStep->setName(STEP_EQ_RECIPE_PARAMETER); |
| | |
| | | |
| | | { |
| | | // FAC Data Report |
| | | CEqReadStep* pStep = new CEqReadStep(0xA60E, 108 * 2, |
| | | CEqReadStep* pStep = new CEqReadStep(m_nIndex == 0 ? 0xA60E : 0xE60E, 108 * 2, |
| | | [&](void* pFrom, int code, const char* pszData, size_t size) -> int { |
| | | if (code == ROK && pszData != nullptr && size > 0) { |
| | | decodePanelDataReport((CStep*)pFrom, pszData, size); |
| | | decodeFacDataReport((CStep*)pFrom, pszData, size); |
| | | } |
| | | return -1; |
| | | }); |
| | |
| | | { |
| | | return m_nIndex == 0 ? 15000 : 20000; |
| | | } |
| | | |
| | | int CBonder::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params) |
| | | { |
| | | ASSERT(pszData); |
| | | if (size < 250) return 0; |
| | | int i = 0, v; |
| | | |
| | | |
| | | // 1.æ ¡æ£å¯¹ä½å»¶æ¶ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("æ ¡æ£å¯¹ä½å»¶æ¶", "", "", v * 0.01f)); |
| | | i += 2; |
| | | |
| | | // 2.ä¿åæ¶é´ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("ä¿åæ¶é´", "", "", v * 0.01f)); |
| | | i += 2; |
| | | |
| | | // 3.è
ä½ç ´çç©ºå»¶æ¶ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("è
ä½ç ´ç空延æ¶", "", "", v * 0.01f)); |
| | | i += 2; |
| | | |
| | | // 4.è
ä½ååæ³µå¯å¨å»¶æ¶ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("è
ä½ååæ³µå¯å¨å»¶æ¶", "", "", v * 0.1f)); |
| | | i += 2; |
| | | |
| | | // 5.è
ä½è´´éæ½çç©ºå»¶æ¶ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("è
ä½è´´éæ½ç空延æ¶", "", "", v * 0.1f)); |
| | | i += 2; |
| | | |
| | | // 6.å ççå¾
å»¶æ¶ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("å ççå¾
å»¶æ¶", "", "", v * 0.1f)); |
| | | i += 2; |
| | | |
| | | // 7.æ°åååè®¾å® |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("æ°ååå设å®", "", "", v * 0.001f)); |
| | | i += 4; |
| | | |
| | | // 8.æ°åå åéç |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("æ°åå åéç", "", "", v * 0.001f)); |
| | | i += 4; |
| | | |
| | | // 9.æ°åæ³åéç |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("æ°åæ³åéç", "", "", v * 0.001f)); |
| | | i += 4; |
| | | |
| | | // 10.è´´éååä¸é |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("è´´éååä¸é", "", "", v * 0.1f)); |
| | | i += 4; |
| | | |
| | | // 11.Z轴转ç©éåº¦è®¾å® |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("ä¸è
Z轴转ç©é度设å®", "", "", v * 0.001f)); |
| | | i += 4; |
| | | |
| | | // 12.ä¸è
æ¸©åº¦è®¾å® |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("ä¸è
温度设å®", "", "", v * 0.1f)); |
| | | i += 2; |
| | | |
| | | // 13.ä¸è
æ¸©åº¦è®¾å® |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("ä¸è
温度设å®", "", "", v * 0.1f)); |
| | | i += 2; |
| | | |
| | | // 14.ä¸è
Zè½´é¢è´´åä½é度 |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("ä¸è
Zè½´é¢è´´åä½é度", "", "", v * 0.001f)); |
| | | i += 4; |
| | | |
| | | // 15.ä¸è
Zè½´è´´éä½é度 |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("ä¸è
Zè½´è´´éä½é度", "", "", v * 0.001f)); |
| | | i += 4; |
| | | |
| | | // 16.ä¸è
Zä¸è
å çä½é´è· |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("ä¸è
Zä¸è
å çä½é´è·", "", "", v * 0.001f)); |
| | | i += 4; |
| | | |
| | | // 17.ä¸è
è´´éä½åå
¥é |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("ä¸è
è´´éä½åå
¥é", "", "", v * 0.001f)); |
| | | i += 4; |
| | | |
| | | // 18.ä¸è
Zè½´ç ´ç空è·ç¦» |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("ä¸è
Zè½´ç ´ç空è·ç¦»", "", "", v * 0.001f)); |
| | | i += 4; |
| | | |
| | | // 19.ä¸é¡¶Pinç ´ç空è·ç¦» |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("ä¸é¡¶Pinç ´ç空è·ç¦»", "", "", v * 0.001f)); |
| | | i += 4; |
| | | |
| | | // 20.ä¸é¡¶Pinå çä½é´è· |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("ä¸é¡¶Pinå çä½é´è·", "", "", v * 0.001f)); |
| | | i += 4; |
| | | |
| | | // 21.è
ä½ç空泵ç空è§è®¾å®å¼ |
| | | params.push_back(CParam("è
ä½ç空泵ç空è§è®¾å®å¼", "", "", (double)toFloat(&pszData[i]))); |
| | | i += 4; |
| | | |
| | | // 22.è
ä½ååæ³µå°è¾¾è®¾å®å¼ |
| | | params.push_back(CParam("è
ä½ååæ³µå°è¾¾è®¾å®å¼", "", "", (double)toFloat(&pszData[i]))); |
| | | i += 4; |
| | | |
| | | |
| | | return (int)params.size(); |
| | | } |
| | | } |
| | |
| | | virtual int onProcessData(CProcessData* pProcessData); |
| | | virtual int onProcessStateChanged(PROCESS_STATE state); |
| | | virtual int getIndexerOperationModeBaseValue(); |
| | | virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms); |
| | | |
| | | public: |
| | | void setIndex(unsigned int index); |
| | |
| | | // 主é
æ¹ä¸æ¥ |
| | | 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); |
| | | |
| | |
| | | CRecipeList* CEquipment::getRecipeList(int unitNo) |
| | | { |
| | | 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) |
| | |
| | | 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); |
| | | LOGI("<CEquipment-%s>请æ±åå
<%d>主é
æ¹åæ°å表失败ï¼code:%d", m_strName.c_str(), unitNo, code); |
| | | } |
| | | |
| | | return 0; |
| | | }); |
| | | }); |
| | | |
| | | return 0; |
| | | } |
| | | |
| | |
| | | std::string strSvTimeRecord, strSvData; |
| | | CToolUnits::convertString(&pszData[index], 8 * 2, strSvTimeRecord); |
| | | index += 128 * 2; |
| | | CToolUnits::convertString(&pszData[index], 640 * 2, strSvData); |
| | | CToolUnits::convertString(&pszData[index], 100 * 2, strSvData); |
| | | index += 256 * 2; |
| | | |
| | | |
| | |
| | | |
| | | 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; |
| | | }; |
| | | } |
| | |
| | | #include "CProcessData.h" |
| | | #include "CPortStatusReport.h" |
| | | #include "CSlot.h" |
| | | #include "CParam.h" |
| | | |
| | | |
| | | namespace SERVO { |
| | |
| | | std::vector<CPin*>& CEquipment::getInputPins(); |
| | | std::vector<CPin*>& CEquipment::getOutputPins(); |
| | | CRecipeList* getRecipeList(int unitNo); |
| | | bool saveRecipeList(int unitNo, std::string& strFilepath); |
| | | bool readRecipeList(int unitNo, std::string& strFilepath); |
| | | virtual int recvIntent(CPin* pPin, CIntent* pIntent); |
| | | virtual int fetchedOutJob(int port, CJobDataB* pJobDataB); |
| | | virtual int storedJob(int port, CJobDataB* pJobDataB, short putSlot); |
| | |
| | | // masterRecipeId: 主é
æ¹id |
| | | // localRecipeId: æ¬å°é
æ¹id |
| | | // unitNo: 0:local; Others:unit No |
| | | int recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo); |
| | | int recipeParameterRequest(short masterRecipeId, short localRecipeId, short unitNo, ONSYNCINGSTATECHANGED block); |
| | | |
| | | // è§£æé
æ¹åæ°å表 |
| | | virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& params) { return 0; }; |
| | | virtual int parsingParams(const char* pszData, size_t size, std::string& strOut); |
| | | |
| | | // è·åæå®çSlot |
| | | CSlot* getSlot(int index); |
| | |
| | | int decodeJobProcessEndReport(CStep* pStep, const char* pszData, size_t size); |
| | | BOOL compareJobData(CJobDataB* pJobDataB, CJobDataS* pJobDataS); |
| | | void setProcessState(PROCESS_STATE state); |
| | | float toFloat(const char* pszAddr); |
| | | |
| | | protected: |
| | | BOOL m_bEnable; |
| | |
| | | |
| | | int CJobDataS::serialize(char* pszBuffer, int nBufferSize) |
| | | { |
| | | if (nBufferSize < 256 * 2) return -1; |
| | | if (nBufferSize < JOBDATAS_SIZE) return -1; |
| | | |
| | | int index = 0; |
| | | memcpy(&pszBuffer[index], &m_nCassetteSequenceNo, sizeof(short)); |
| | |
| | | memcpy(&pszBuffer[index], &m_nFirstGlassFlag, sizeof(short)); |
| | | index += sizeof(short); |
| | | |
| | | memcpy(&pszBuffer[index], &m_nLastGlassFlag, sizeof(short)); |
| | | index += sizeof(short); |
| | | |
| | | memcpy(&pszBuffer[index], &m_nQTime[0], sizeof(short)); |
| | | index += sizeof(short); |
| | | |
| | |
| | | memcpy(&pszBuffer[index], &m_nProductJudge, sizeof(short)); |
| | | index += sizeof(short); |
| | | |
| | | return 256 * 2; |
| | | return JOBDATAS_SIZE; |
| | | } |
| | | |
| | | int CJobDataS::unserialize(const char* pszBuffer, int nBufferSize) |
| | |
| | | char szBuffer[64]; |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | if (!m_slot[i].isEnable()) continue; |
| | | if (!(map >> i) & 1) continue; |
| | | if (((map >> i) & 1) == 0) continue; |
| | | |
| | | CJobDataS js; |
| | | js.setCassetteSequenceNo(getNextCassetteSequenceNo()); |
| | |
| | | && pLoadPorts[s]->getPortStatus() == PORT_INUSE) { |
| | | m_pActiveRobotTask = createTransferTask(pLoadPorts[s], pAligner, primaryType, secondaryType, 1, m_bJobMode); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | CGlass* pGlass = (CGlass*)m_pActiveRobotTask->getContext(); |
| | | if (pGlass->getBuddy() != nullptr) { |
| | | delete m_pActiveRobotTask; |
| | | m_pActiveRobotTask = nullptr; |
| | | continue; |
| | | } |
| | | |
| | | pEFEM->setContext(m_pActiveRobotTask->getContext()); |
| | | goto PORT_GET; |
| | | } |
| | |
| | | m_pActiveRobotTask = createTransferTask(pLoadPorts[s], pAligner, primaryType, secondaryType, m_bJobMode); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | CGlass* pGlass = (CGlass*)m_pActiveRobotTask->getContext(); |
| | | if (pGlass->getBuddy() != nullptr) { |
| | | delete m_pActiveRobotTask; |
| | | m_pActiveRobotTask = nullptr; |
| | | continue; |
| | | } |
| | | |
| | | pEFEM->setContext(pGlass); |
| | | pGlass->start(); |
| | | bool bMoved = glassFromQueueToInPorcess(pGlass); |
| | |
| | | m_pControlJob = new CControlJob(); |
| | | if (!CControlJob::deserialize(ifs, *m_pControlJob)) return false; |
| | | } |
| | | |
| | | else { |
| | | return false; |
| | | } |
| | | |
| | | // 读å ProcessJob å表 |
| | | uint32_t count = 0; |
| | |
| | | |
| | | { |
| | | // 请æ±é
æ¹åæ° |
| | | //CEqWriteStep* pStep = new CEqWriteStep(); |
| | | //pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ); |
| | | //pStep->setWriteSignalDev(0xf67); |
| | | //pStep->setDataDev(0x379b); |
| | | //if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) { |
| | | // delete pStep; |
| | | //} |
| | | CEqWriteStep* pStep = new CEqWriteStep(); |
| | | pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ); |
| | | pStep->setWriteSignalDev(0xf67); |
| | | pStep->setDataDev(0x379b); |
| | | if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) { |
| | | delete pStep; |
| | | } |
| | | } |
| | | |
| | | { |
| | | // recipe parameter report |
| | | //CEqReadStep* pStep = new CEqReadStep(0x1aa54, 257 * 2, |
| | | // [&](void* pFrom, int code, const char* pszData, size_t size) -> int { |
| | | // if (code == ROK && pszData != nullptr && size > 0) { |
| | | // // æ¤å¤è§£éé
æ¹æ°æ® |
| | | // short ret = decodeRecipeParameterReport(pszData, size); |
| | | // pStep->setReturnCode(ret); |
| | | // } |
| | | // pStep->setReturnCode(MRLRC_OK); |
| | | // return -1; |
| | | // }); |
| | | //pStep->setName(STEP_EQ_RECIPE_PARAMETER); |
| | | //pStep->setWriteSignalDev(0xf4c); |
| | | //pStep->setReturnDev(m_nIndex == 0 ? 0x126c : 0x1bbc); |
| | | //if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) { |
| | | // delete pStep; |
| | | //} |
| | | CEqReadStep* pStep = new CEqReadStep(0x1aa54, 257 * 2, |
| | | [&](void* pFrom, int code, const char* pszData, size_t size) -> int { |
| | | CEqReadStep* pTmpStep = (CEqReadStep*)pFrom; |
| | | if (code == ROK && pszData != nullptr && size > 0) { |
| | | // æ¤å¤è§£éé
æ¹æ°æ® |
| | | short ret = decodeRecipeParameterReport(pszData, size); |
| | | pTmpStep->setReturnCode(ret); |
| | | } |
| | | pTmpStep->setReturnCode(MRLRC_OK); |
| | | return -1; |
| | | }); |
| | | pStep->setName(STEP_EQ_RECIPE_PARAMETER); |
| | | pStep->setWriteSignalDev(0xf4c); |
| | | pStep->setReturnDev(0x37ac); |
| | | if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) { |
| | | delete pStep; |
| | | } |
| | | } |
| | | |
| | | // 使ç¨CEqReadStepæ¿æ¢CEqJobEventStep |
| | |
| | | { |
| | | return 35000; |
| | | } |
| | | |
| | | int CMeasurement::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params) |
| | | { |
| | | ASSERT(pszData); |
| | | if (size < 250) return 0; |
| | | int i = 0, v; |
| | | |
| | | |
| | | // 1.æ£æµåè½å¯ç¨/ç¦ç¨ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("æ£æµåè½å¯ç¨/ç¦ç¨", "", "", v)); |
| | | i += 2; |
| | | |
| | | // 2.æ£æµé度 |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("æ£æµé度", "", "", v * 0.001)); |
| | | i += 4; |
| | | |
| | | return (int)params.size(); |
| | | } |
| | | } |
| | |
| | | virtual void getAttributeVector(CAttributeVector& attrubutes); |
| | | virtual int recvIntent(CPin* pPin, CIntent* pIntent); |
| | | virtual int getIndexerOperationModeBaseValue(); |
| | | virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms); |
| | | }; |
| | | } |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "CParam.h" |
| | | |
| | | |
| | | CParam::CParam() |
| | | { |
| | | m_nValueType = PVT_INT; |
| | | m_nValue = 0; |
| | | m_fValue = 0.0; |
| | | } |
| | | |
| | | CParam::CParam(const char* pszName, const char* pszId, const char* pszUnit, int value) |
| | | { |
| | | m_nValueType = PVT_INT; |
| | | m_nValue = value; |
| | | m_fValue = 0.0; |
| | | m_strId = pszId; |
| | | m_strName = pszName; |
| | | m_strUnit = pszUnit; |
| | | } |
| | | |
| | | CParam::CParam(const char* pszName, const char* pszId, const char* pszUnit, double value) |
| | | { |
| | | m_nValueType = PVT_DOUBLE; |
| | | m_nValue = 0; |
| | | m_fValue = value; |
| | | m_strId = pszId; |
| | | m_strName = pszName; |
| | | m_strUnit = pszUnit; |
| | | } |
| | | |
| | | CParam::~CParam() |
| | | { |
| | | } |
| | | |
| | | std::string& CParam::getName() |
| | | { |
| | | return m_strName; |
| | | } |
| | | |
| | | std::string& CParam::getId() |
| | | { |
| | | return m_strId; |
| | | } |
| | | |
| | | std::string& CParam::getUnit() |
| | | { |
| | | return m_strUnit; |
| | | } |
| | | |
| | | int CParam::getValueType() |
| | | { |
| | | return m_nValueType; |
| | | } |
| | | |
| | | int CParam::getIntValue() |
| | | { |
| | | return m_nValue; |
| | | } |
| | | |
| | | void CParam::setIntValue(int value) |
| | | { |
| | | m_nValue = value; |
| | | } |
| | | |
| | | double CParam::getDoubleValue() |
| | | { |
| | | return m_fValue; |
| | | } |
| | | |
| | | void CParam::setDoubleValue(double value) |
| | | { |
| | | m_fValue = value; |
| | | } |
| | | |
| | | void CParam::Serialize(CArchive& ar) |
| | | { |
| | | if (ar.IsStoring()) |
| | | { |
| | | WriteString(ar, m_strName); |
| | | WriteString(ar, m_strUnit); |
| | | ar << m_nValueType; |
| | | ar << m_nValue; |
| | | ar << m_fValue; |
| | | } |
| | | else |
| | | { |
| | | ReadString(ar, m_strName); |
| | | ReadString(ar, m_strUnit); |
| | | ar >> m_nValueType; |
| | | ar >> m_nValue; |
| | | ar >> m_fValue; |
| | | } |
| | | } |
| | | |
| | | void CParam::ReadString(CArchive& ar, std::string& string) |
| | | { |
| | | CString strTemp; |
| | | ar >> strTemp; |
| | | string = (LPTSTR)(LPCTSTR)strTemp; |
| | | } |
| | | |
| | | void CParam::WriteString(CArchive& ar, std::string& string) |
| | | { |
| | | CString strTemp = string.c_str(); |
| | | ar << strTemp; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include <string> |
| | | |
| | | #define PVT_INT 0 |
| | | #define PVT_DOUBLE 1 |
| | | |
| | | class CParam |
| | | { |
| | | public: |
| | | CParam(); |
| | | CParam(const char* pszName, const char* pszId, const char* pszUnit, int value); |
| | | CParam(const char* pszName, const char* pszId, const char* pszUnit, double value); |
| | | ~CParam(); |
| | | |
| | | public: |
| | | std::string& getId(); |
| | | std::string& getName(); |
| | | std::string& getUnit(); |
| | | int getValueType(); |
| | | int getIntValue(); |
| | | void setIntValue(int value); |
| | | double getDoubleValue(); |
| | | void setDoubleValue(double value); |
| | | void Serialize(CArchive& ar); |
| | | |
| | | private: |
| | | void ReadString(CArchive& ar, std::string& string); |
| | | void WriteString(CArchive& ar, std::string& string); |
| | | |
| | | private: |
| | | int m_nValueType; |
| | | std::string m_strId; |
| | | std::string m_strName; |
| | | std::string m_strUnit; |
| | | int m_nValue; |
| | | double m_fValue; |
| | | }; |
| | | |
| | |
| | | #include "CRecipeList.h" |
| | | #include "Common.h" |
| | | #include "ToolUnits.h" |
| | | #include <fstream> |
| | | |
| | | |
| | | namespace SERVO { |
| | |
| | | } |
| | | |
| | | if (m_nCurrentGroupCount == m_nToatlGroupCount) { |
| | | m_nToatlGroupCount = 0; |
| | | m_nCurrentGroupCount = 0; |
| | | return MRLRC_CURRENT_RECIPE_COMPLETE; |
| | | } |
| | | |
| | |
| | | return m_ids; |
| | | } |
| | | |
| | | std::unordered_map<short, std::vector<uint8_t>>& CRecipeList::getParamsRawData() |
| | | { |
| | | return m_paramsRawData; |
| | | } |
| | | |
| | | void CRecipeList::reset() |
| | | { |
| | | m_nToatlGroupCount = 0; |
| | | m_nCurrentGroupCount = 0; |
| | | m_ids.clear(); |
| | | m_paramsRawData.clear(); |
| | | } |
| | | |
| | | void CRecipeList::reset2() |
| | | { |
| | | m_nToatlGroupCount = 0; |
| | | m_nCurrentGroupCount = 0; |
| | | } |
| | | |
| | | int CRecipeList::addParamsPacket(int totalCount, int totalGroup, int currentGroup, |
| | | short unitId, short recipeId, |
| | | const char* pszData, size_t size) |
| | | { |
| | | if (m_nToatlGroupCount == 0) m_nToatlGroupCount = totalGroup; |
| | | if (m_nToatlGroupCount != totalGroup) { |
| | | reset2(); |
| | | return MRLRC_GROUP_COUNT_NG; |
| | | } |
| | | if (currentGroup == 0) { |
| | | reset2(); |
| | | } |
| | | if (m_nCurrentGroupCount + 1 > currentGroup) { |
| | | return MRLRC_DUPLICATION_GROUP_COUNT_NG; |
| | | } |
| | | if (m_nCurrentGroupCount + 1 < currentGroup) { |
| | | return ORDER_BY_GROUP_COUNT_NG; |
| | | } |
| | | m_nCurrentGroupCount++; |
| | | |
| | | m_paramsRawData[recipeId].insert(m_paramsRawData[recipeId].end(), (uint8_t*)(pszData), (uint8_t*)(pszData) + size); |
| | | if (m_nCurrentGroupCount == m_nToatlGroupCount) { |
| | | // è§£éæ°æ®å°±äº¤ç»åºç¨å±å§ |
| | | reset2(); |
| | | |
| | | return MRLRC_CURRENT_RECIPE_COMPLETE; |
| | | } |
| | | |
| | | |
| | | return MRLRC_CONTINUE; |
| | | } |
| | | |
| | | // åºåå |
| | | bool CRecipeList::serialize(const std::string& filename) const |
| | | { |
| | | std::ofstream ofs(filename, std::ios::binary); |
| | | if (!ofs) return false; |
| | | |
| | | // ååºæ¬æå |
| | | ofs.write(reinterpret_cast<const char*>(&m_nUnitNo), sizeof(m_nUnitNo)); |
| | | ofs.write(reinterpret_cast<const char*>(&m_nToatlGroupCount), sizeof(m_nToatlGroupCount)); |
| | | ofs.write(reinterpret_cast<const char*>(&m_nCurrentGroupCount), sizeof(m_nCurrentGroupCount)); |
| | | |
| | | // д m_ids |
| | | size_t idsSize = m_ids.size(); |
| | | ofs.write(reinterpret_cast<const char*>(&idsSize), sizeof(idsSize)); |
| | | for (auto& kv : m_ids) { |
| | | ofs.write(reinterpret_cast<const char*>(&kv.first), sizeof(kv.first)); |
| | | ofs.write(reinterpret_cast<const char*>(&kv.second), sizeof(kv.second)); |
| | | } |
| | | |
| | | // д m_paramsRawData |
| | | size_t paramsSize = m_paramsRawData.size(); |
| | | ofs.write(reinterpret_cast<const char*>(¶msSize), sizeof(paramsSize)); |
| | | for (auto& kv : m_paramsRawData) { |
| | | // д key |
| | | ofs.write(reinterpret_cast<const char*>(&kv.first), sizeof(kv.first)); |
| | | |
| | | // å vector å¤§å° |
| | | size_t vecSize = kv.second.size(); |
| | | ofs.write(reinterpret_cast<const char*>(&vecSize), sizeof(vecSize)); |
| | | |
| | | // å vector å
容 |
| | | if (!kv.second.empty()) { |
| | | ofs.write(reinterpret_cast<const char*>(kv.second.data()), vecSize); |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | // ååºåå |
| | | bool CRecipeList::deserialize(const std::string& filename) |
| | | { |
| | | std::ifstream ifs(filename, std::ios::binary); |
| | | if (!ifs) return false; |
| | | |
| | | reset(); // æ¸
ç©ºæ§æ°æ® |
| | | |
| | | // è¯»åºæ¬æå |
| | | ifs.read(reinterpret_cast<char*>(&m_nUnitNo), sizeof(m_nUnitNo)); |
| | | ifs.read(reinterpret_cast<char*>(&m_nToatlGroupCount), sizeof(m_nToatlGroupCount)); |
| | | ifs.read(reinterpret_cast<char*>(&m_nCurrentGroupCount), sizeof(m_nCurrentGroupCount)); |
| | | |
| | | // 读 m_ids |
| | | size_t idsSize = 0; |
| | | ifs.read(reinterpret_cast<char*>(&idsSize), sizeof(idsSize)); |
| | | for (size_t i = 0; i < idsSize; ++i) { |
| | | int key; |
| | | short value; |
| | | ifs.read(reinterpret_cast<char*>(&key), sizeof(key)); |
| | | ifs.read(reinterpret_cast<char*>(&value), sizeof(value)); |
| | | m_ids[key] = value; |
| | | } |
| | | |
| | | // 读 m_paramsRawData |
| | | size_t paramsSize = 0; |
| | | ifs.read(reinterpret_cast<char*>(¶msSize), sizeof(paramsSize)); |
| | | for (size_t i = 0; i < paramsSize; ++i) { |
| | | short key; |
| | | size_t vecSize = 0; |
| | | ifs.read(reinterpret_cast<char*>(&key), sizeof(key)); |
| | | ifs.read(reinterpret_cast<char*>(&vecSize), sizeof(vecSize)); |
| | | |
| | | std::vector<uint8_t> buffer(vecSize); |
| | | if (vecSize > 0) { |
| | | ifs.read(reinterpret_cast<char*>(buffer.data()), vecSize); |
| | | } |
| | | m_paramsRawData[key] = std::move(buffer); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | } |
| | |
| | | #pragma once |
| | | #pragma once |
| | | #include <map> |
| | | |
| | | |
| | |
| | | int addRecipePacket(int totalCount,int totalGroup, int currentGroup, const char* pszData, size_t size); |
| | | int addRecipe(int index, short id); |
| | | std::map<int, short>& getIds(); |
| | | std::unordered_map<short, std::vector<uint8_t>>& getParamsRawData(); |
| | | void reset(); |
| | | void reset2(); |
| | | |
| | | // æ·»å åæ°å
|
| | | int addParamsPacket(int totalCount, int totalGroup, int currentGroup, |
| | | short unitId, short recipeId, |
| | | const char* pszData, size_t size); |
| | | |
| | | // â æ°å¢åºåååååºåå彿° |
| | | bool serialize(const std::string& filename) const; |
| | | bool deserialize(const std::string& filename); |
| | | |
| | | private: |
| | | int m_nUnitNo; |
| | | int m_nToatlGroupCount; |
| | | int m_nCurrentGroupCount; |
| | | std::map<int, short> m_ids; |
| | | std::unordered_map<short, std::vector<uint8_t>> m_paramsRawData; |
| | | }; |
| | | } |
| | | |
| | |
| | | } |
| | | m_mapRecipes = m_mapRecipesTemp; |
| | | m_mapRecipesTemp.clear(); |
| | | m_nSyncStatus = SS_COMPLETE; |
| | | m_nSyncStatus = SS_LIST_COMPLETE; |
| | | unlock(); |
| | | |
| | | if (m_onSyncingStateChanged != nullptr) { |
| | |
| | | |
| | | |
| | | |
| | | // æ¾å°å¯¹åºCRecipeList, æ¾ä¸å°åæ°å»º |
| | | /* |
| | | // æ¾å°å¯¹åºCRecipeList, æ¾ä¸å°åè¿åNG |
| | | lock(); |
| | | CRecipeList* pRecipeList = getRecipeListFromTemp(unitNo); |
| | | CRecipeList* pRecipeList = getRecipeList(unitNo); |
| | | if (pRecipeList == nullptr) { |
| | | pRecipeList = new CRecipeList(unitNo); |
| | | m_mapRecipesTemp[unitNo] = pRecipeList; |
| | | unlock(); |
| | | return MRLRC_NG; |
| | | } |
| | | unlock(); |
| | | ASSERT(pRecipeList); |
| | | */ |
| | | |
| | | /* |
| | | 1: Create |
| | |
| | | 3: Delete |
| | | 4: Request from EAS |
| | | */ |
| | | /* |
| | | if (reportType == RT_CREATE) { |
| | | |
| | | } |
| | |
| | | |
| | | } |
| | | else if (reportType == RT_REQUEST_FROM_EAS) { |
| | | int nRet = pRecipeList->addRecipePacket(toatlGroupCount, currentGroupCount, pszIdsData, 250 * 2); |
| | | int nRet = pRecipeList->addParamsPacket(totalParameterCount, toatlGroupCount, currentGroupCount, |
| | | unitNo, localRecipeId, |
| | | pszParameterData, 250 * 2); |
| | | if (MRLRC_CURRENT_RECIPE_COMPLETE == nRet) { |
| | | lock(); |
| | | if (m_nTotalMasterRecipeCount == m_mapRecipesTemp.size()) { |
| | | for (auto item : m_mapRecipes) { |
| | | delete item.second; |
| | | } |
| | | m_mapRecipes = m_mapRecipesTemp; |
| | | m_mapRecipesTemp.clear(); |
| | | m_nSyncStatus = SS_COMPLETE; |
| | | unlock(); |
| | | return MRLRC_OK; |
| | | } |
| | | m_nSyncStatus = SS_PARAMS_COMPLETE; |
| | | unlock(); |
| | | |
| | | if (m_onSyncingStateChanged != nullptr) { |
| | | m_onSyncingStateChanged(m_nSyncStatus); |
| | | } |
| | | |
| | | return MRLRC_OK; |
| | | } |
| | | else if (MRLRC_CONTINUE == nRet) { |
| | | return MRLRC_CONTINUE; |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | */ |
| | | |
| | | |
| | | return MRLRC_OK; |
| | | } |
| | |
| | | return iter->second; |
| | | } |
| | | |
| | | bool CRecipesManager::saveRecipeList(int unitNo, std::string& strFilepath) |
| | | { |
| | | CRecipeList* pRecipeList = getRecipeList(unitNo); |
| | | if (pRecipeList == nullptr) return false; |
| | | return pRecipeList->serialize(strFilepath); |
| | | } |
| | | |
| | | bool CRecipesManager::readRecipeList(int unitNo, std::string& strFilepath) |
| | | { |
| | | CRecipeList* pRecipeList = getRecipeList(unitNo); |
| | | if (pRecipeList == nullptr) { |
| | | pRecipeList = new CRecipeList(); |
| | | m_mapRecipes[unitNo] = pRecipeList; |
| | | } |
| | | return pRecipeList->deserialize(strFilepath); |
| | | } |
| | | |
| | | void CRecipesManager::setOnSyncingStateChanged(ONSYNCINGSTATECHANGED block) |
| | | { |
| | | m_onSyncingStateChanged = block; |
| | |
| | | |
| | | #define SS_NONE 0 |
| | | #define SS_SYNCING 1 |
| | | #define SS_COMPLETE 2 |
| | | #define SS_TIMEOUT 3 |
| | | #define SS_FAILED 4 |
| | | #define SS_LIST_COMPLETE 2 |
| | | #define SS_PARAMS_COMPLETE 3 |
| | | #define SS_TIMEOUT 4 |
| | | #define SS_FAILED 5 |
| | | |
| | | namespace SERVO { |
| | | typedef std::function<void(int state)> ONSYNCINGSTATECHANGED; |
| | |
| | | short decodeRecipeParameterReport(const char* pszData, size_t size); |
| | | CRecipeList* getRecipeListFromTemp(int unitNo); |
| | | CRecipeList* getRecipeList(int unitNo); |
| | | bool saveRecipeList(int unitNo, std::string& strFilepath); |
| | | bool readRecipeList(int unitNo, std::string& strFilepath); |
| | | |
| | | public: |
| | | inline void lock() { ::EnterCriticalSection(&m_cs); }; |
| | |
| | | LOGI(_T("RobotTaskå·²ä¸åå°EFEM")); |
| | | } |
| | | else { |
| | | LOGI(_T("RobotTaskå·²ä¸å失败")); |
| | | LOGI(_T("RobotTaskä¸å失败")); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | |
| | | { |
| | | // 请æ±é
æ¹åæ° |
| | | //CEqWriteStep* pStep = new CEqWriteStep(); |
| | | //pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ); |
| | | //pStep->setWriteSignalDev(0xc67); |
| | | //pStep->setDataDev(0x379b); |
| | | //if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) { |
| | | // delete pStep; |
| | | //} |
| | | CEqWriteStep* pStep = new CEqWriteStep(); |
| | | pStep->setName(STEP_EQ_RECIPE_PARAMETER_REQ); |
| | | pStep->setWriteSignalDev(0xc67); |
| | | pStep->setDataDev(0x2e4b); |
| | | if (addStep(STEP_ID_RECIPE_PARAMETER_CMD_REPLY, pStep) != 0) { |
| | | delete pStep; |
| | | } |
| | | } |
| | | |
| | | { |
| | | // recipe parameter report |
| | | //CEqReadStep* pStep = new CEqReadStep(0x1aa54, 257 * 2, |
| | | // [&](void* pFrom, int code, const char* pszData, size_t size) -> int { |
| | | // if (code == ROK && pszData != nullptr && size > 0) { |
| | | // // æ¤å¤è§£éé
æ¹æ°æ® |
| | | // short ret = decodeRecipeParameterReport(pszData, size); |
| | | // pStep->setReturnCode(ret); |
| | | // } |
| | | // pStep->setReturnCode(MRLRC_OK); |
| | | // return -1; |
| | | // }); |
| | | //pStep->setName(STEP_EQ_RECIPE_PARAMETER); |
| | | //pStep->setWriteSignalDev(0xc4c); |
| | | //pStep->setReturnDev(m_nIndex == 0 ? 0x126c : 0x1bbc); |
| | | //if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) { |
| | | // delete pStep; |
| | | //} |
| | | CEqReadStep* pStep = new CEqReadStep(0x16a54, 257 * 2, |
| | | [&](void* pFrom, int code, const char* pszData, size_t size) -> int { |
| | | CEqReadStep* pTmpStep = (CEqReadStep*)pFrom; |
| | | if (code == ROK && pszData != nullptr && size > 0) { |
| | | // æ¤å¤è§£éé
æ¹æ°æ® |
| | | short ret = decodeRecipeParameterReport(pszData, size); |
| | | pTmpStep->setReturnCode(ret); |
| | | } |
| | | pTmpStep->setReturnCode(MRLRC_OK); |
| | | return -1; |
| | | }); |
| | | pStep->setName(STEP_EQ_RECIPE_PARAMETER); |
| | | pStep->setWriteSignalDev(0xc4c); |
| | | pStep->setReturnDev(0x2ec); |
| | | if (addStep(STEP_ID_RECIPE_PARAMETER_REPORT, pStep) != 0) { |
| | | delete pStep; |
| | | } |
| | | } |
| | | |
| | | // 使ç¨CEqReadStepæ¿æ¢CEqJobEventStep |
| | |
| | | { |
| | | return 30000; |
| | | } |
| | | |
| | | int CVacuumBake::parsingParams(const char* pszData, size_t size, std::vector<CParam>& params) |
| | | { |
| | | ASSERT(pszData); |
| | | if (size < 250) return 0; |
| | | int i = 0, v; |
| | | |
| | | |
| | | // 1.A_è
å çæ¶é´ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("A_è
å çæ¶é´", "", "", v * 0.1f)); |
| | | i += 2; |
| | | |
| | | // 2.B_è
å çæ¶é´ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("B_è
å çæ¶é´", "", "", v * 0.1f)); |
| | | i += 2; |
| | | |
| | | // 3.A_è
ç ´ç空æ¶é´ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("A_è
ç ´ç空æ¶é´", "", "", v * 0.01f)); |
| | | i += 2; |
| | | |
| | | // 4.B_è
ç ´ç空æ¶é´ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("B_è
ç ´ç空æ¶é´", "", "", v * 0.01f)); |
| | | i += 2; |
| | | |
| | | // 5.A_è
ç空å°è¾¾å¼ |
| | | params.push_back(CParam("A_è
ç空å°è¾¾å¼", "", "", (double)toFloat(&pszData[i]))); |
| | | i += 4; |
| | | |
| | | // 6.B_è
ç空å°è¾¾å¼ |
| | | params.push_back(CParam("B_è
ç空å°è¾¾å¼", "", "", (double)toFloat(&pszData[i]))); |
| | | i += 4; |
| | | |
| | | // 7.A_è
温æ§è¡¨ä¸»æ§æ¸©åº¦è®¾å® |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("A_è
温æ§è¡¨ä¸»æ§æ¸©åº¦è®¾å®", "", "", v * 0.1f)); |
| | | i += 4; |
| | | |
| | | // 8.B_è
温æ§è¡¨ä¸»æ§æ¸©åº¦è®¾å® |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("B_è
温æ§è¡¨ä¸»æ§æ¸©åº¦è®¾å®", "", "", v * 0.1f)); |
| | | i += 4; |
| | | |
| | | |
| | | return (int)params.size(); |
| | | } |
| | | } |
| | |
| | | virtual void getAttributeVector(CAttributeVector& attrubutes); |
| | | virtual int recvIntent(CPin* pPin, CIntent* pIntent); |
| | | virtual int getIndexerOperationModeBaseValue(); |
| | | |
| | | virtual int parsingParams(const char* pszData, size_t size, std::vector<CParam>& parsms); |
| | | }; |
| | | } |
| | | |
| | |
| | | #include "afxdialogex.h" |
| | | #include "PageRecipe.h" |
| | | #include "MsgDlg.h" |
| | | #include "InputDialog.h" |
| | | #include "RecipeDeviceBindDlg.h" |
| | | |
| | | |
| | | // CPageRecipe å¯¹è¯æ¡ |
| | | |
| | |
| | | |
| | | CString strIniFile, strItem; |
| | | strIniFile.Format(_T("%s\\configuration.ini"), (LPCTSTR)theApp.m_strAppDir); |
| | | int width[] = { 0, 60, 150, 150 }; |
| | | int width[] = { 0, 60, 100, 100, 150 }; |
| | | |
| | | for (int i = 0; i < 4; i++) { |
| | | for (int i = 0; i < 5; i++) { |
| | | strItem.Format(_T("Col_Device_%d_Width"), i); |
| | | width[i] = GetPrivateProfileInt(_T("PageRecipeListCtrl"), strItem, width[i], strIniFile); |
| | | } |
| | |
| | | m_listPPID.InsertColumn(1, _T("No."), LVCFMT_CENTER, width[1]); |
| | | m_listPPID.InsertColumn(2, _T("Recipe ID"), LVCFMT_CENTER, width[2]); |
| | | m_listPPID.InsertColumn(3, _T("Recipe åç§°"), LVCFMT_CENTER, width[3]); |
| | | m_listPPID.InsertColumn(4, _T("Recipe åæ°"), LVCFMT_CENTER, width[4]); |
| | | } |
| | | |
| | | void CPageRecipe::UpdateRecipeByPPID(const CString& strPPID) |
| | |
| | | m_listPPID.SetItemText(i, 2, CA2T(recipe.strPPID.c_str())); |
| | | |
| | | for (int j = 0; j < recipe.vecDeviceList.size(); j++){ |
| | | int nRecipeID = recipe.vecDeviceList.at(j).nRecipeID; |
| | | std::string strDeviceName = recipe.vecDeviceList.at(j).strDeviceName; |
| | | std::string strRecipeName = RecipeManager::getInstance().getDeviceRecipeName(strDeviceName, nRecipeID); |
| | | |
| | | CString str; |
| | | str.Format(_T("%d"), recipe.vecDeviceList.at(j).nRecipeID); |
| | | if (strRecipeName.empty()) { |
| | | str.Format(_T("%d"), recipe.vecDeviceList.at(j).nRecipeID); |
| | | } |
| | | else { |
| | | str.Format(_T("%s"), CA2T(strRecipeName.c_str())); |
| | | } |
| | | |
| | | m_listPPID.SetItemText(i, j + 3, str); |
| | | } |
| | | |
| | |
| | | m_listPPID.SetColumnWidth(nColCount - 1, LVSCW_AUTOSIZE_USEHEADER); |
| | | } |
| | | |
| | | void CPageRecipe::FillRecipeListToListCtrl(SERVO::CRecipeList* pList) |
| | | void CPageRecipe::FillRecipeListToListCtrl(SERVO::CEquipment* pEq) |
| | | { |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_PPID); |
| | | if (pListCtrl == nullptr || !::IsWindow(pListCtrl->m_hWnd)) { |
| | | return; |
| | |
| | | |
| | | // æ¸
空å½åCListCtrlä¸çææé¡¹ |
| | | pListCtrl->DeleteAllItems(); |
| | | if (pList == nullptr) { |
| | | if (pRecipeList == nullptr) { |
| | | return; |
| | | } |
| | | |
| | | // éåæ°æ®å¹¶æå
¥å°CListCtrlä¸ |
| | | std::map<int, short>& ids = pList->getIds(); |
| | | auto& mgr = RecipeManager::getInstance(); |
| | | std::map<int, short>& ids = pRecipeList->getIds(); |
| | | auto rawDatas = pRecipeList->getParamsRawData(); |
| | | for (auto item : ids) { |
| | | int index = m_listPPID.InsertItem(m_listPPID.GetItemCount(), _T("")); |
| | | m_listPPID.SetItemText(index, 1, std::to_string(item.first).c_str()); |
| | | m_listPPID.SetItemText(index, 2, std::to_string(item.second).c_str()); |
| | | |
| | | std::string strRecipeName = mgr.getDeviceRecipeName(pEq->getName(), item.second); |
| | | m_listPPID.SetItemText(index, 3, strRecipeName.c_str()); |
| | | |
| | | std::string strDescription; |
| | | auto iter = rawDatas.find(item.second); |
| | | if (iter != rawDatas.end()) { |
| | | pEq->parsingParams((const char*)iter->second.data(), iter->second.size(), strDescription); |
| | | m_listPPID.SetItemText(index, 4, strDescription.c_str()); |
| | | } |
| | | |
| | | if (strRecipeName.empty()) { |
| | | strRecipeName = std::to_string(item.second); |
| | | mgr.addDeviceRecipe(pEq->getName(), item.second, strRecipeName, strDescription); |
| | | } |
| | | } |
| | | |
| | | // è·ååæ° |
| | |
| | | ON_BN_CLICKED(IDC_BUTTON_DELETE, &CPageRecipe::OnBnClickedButtonDelete) |
| | | ON_BN_CLICKED(IDC_BUTTON_DELETE_ALL, &CPageRecipe::OnBnClickedButtonDeleteAll) |
| | | ON_BN_CLICKED(IDC_BUTTON_REFRESH, &CPageRecipe::OnBnClickedButtonRefresh) |
| | | ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_PPID, &CPageRecipe::OnLvnItemChangedListPPID) |
| | | ON_NOTIFY(NM_CLICK, IDC_LIST_PPID, &CPageRecipe::OnClickListPPID) |
| | | ON_NOTIFY(NM_DBLCLK, IDC_LIST_PPID, &CPageRecipe::OnDblclkListPPID) |
| | | ON_CBN_SELCHANGE(IDC_COMBO_EQUIPMENT, &CPageRecipe::OnCbnSelchangeComboEquipment) |
| | | END_MESSAGE_MAP() |
| | | |
| | |
| | | pEq[i] == nullptr ? _T("Master") : pEq[i]->getName().c_str()); |
| | | pComboBox->SetItemDataPtr(i, pEq[i]); |
| | | |
| | | // 读å忥 |
| | | char szBuffer[_MAX_PATH]; |
| | | if (pEq[i]) { |
| | | pEq[i]->masterRecipeListRequest(0, nullptr); |
| | | sprintf_s(szBuffer, _MAX_PATH, "%s\\Recipe\\EQ%d_Unit0.recipelist", (LPTSTR)(LPCTSTR)theApp.m_strAppDir, pEq[i]->getID()); |
| | | std::string strFilepath(szBuffer); |
| | | pEq[i]->readRecipeList(0, strFilepath); |
| | | } |
| | | } |
| | | pComboBox->SetCurSel(0); |
| | |
| | | void CPageRecipe::OnBnClickedButtonModify() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); |
| | | if (pComboBox == nullptr || !::IsWindow(pComboBox->m_hWnd)) { |
| | | return; |
| | | } |
| | | |
| | | POSITION pos = m_listPPID.GetFirstSelectedItemPosition(); |
| | | if (!pos) { |
| | | AfxMessageBox(_T("请å
鿩䏿¡é
æ¹è®°å½è¿è¡ä¿®æ¹ï¼")); |
| | | return; |
| | | } |
| | | |
| | | int nSel = m_listPPID.GetNextSelectedItem(pos); |
| | | CString strPPID = m_listPPID.GetItemText(nSel, 2); |
| | | UpdateRecipeByPPID(strPPID); |
| | | int nLine = m_listPPID.GetNextSelectedItem(pos); |
| | | CString strID = m_listPPID.GetItemText(nLine, 2); |
| | | |
| | | int nSel = pComboBox->GetCurSel(); |
| | | SERVO::CEquipment* pEq = (SERVO::CEquipment*)pComboBox->GetItemDataPtr(nSel); |
| | | if (pEq == nullptr) { |
| | | UpdateRecipeByPPID(strID); |
| | | } |
| | | else { |
| | | CInputDialog dlg(_T("ä¿®æ¹é
æ¹åç§°"), _T("请è¾å
¥é
æ¹åç§°ï¼")); |
| | | if (dlg.DoModal() != IDOK) { |
| | | return; |
| | | } |
| | | |
| | | CString strText = dlg.GetInputText(); |
| | | if (strText.IsEmpty()) { |
| | | AfxMessageBox(_T("é
æ¹åç§°ä¸è½ä¸ºç©ºï¼")); |
| | | return; |
| | | } |
| | | |
| | | if (RecipeManager::getInstance().updateDeviceRecipeName(pEq->getName(), _ttoi(strID), std::string(CT2A(strText)))) { |
| | | m_listPPID.SetItemText(nLine, 3, strText); |
| | | } |
| | | } |
| | | } |
| | | |
| | | void CPageRecipe::OnBnClickedButtonDelete() |
| | |
| | | FillDataToListCtrl(vecData); |
| | | } |
| | | else { |
| | | // enable port |
| | | CMsgDlg msgDlg("请çå¾
", "æ£å¨è·åé
æ¹..."); |
| | | pEq->masterRecipeListRequest(0, [&, pEq](int status) -> void { |
| | | if (status == SS_FAILED || status == SS_TIMEOUT) { |
| | | CString strMsg; |
| | | strMsg.Format(status == SS_FAILED ? _T("è·åé
æ¹å¤±è´¥ï¼") : _T("è·åé
æ¹è¶
æ¶ï¼")); |
| | | msgDlg.DelayClose(3000); |
| | | msgDlg.SetIcon(MSG_BOX_ERROR); |
| | | msgDlg.SetTitle(_T("æä½å¤±è´¥")); |
| | | msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | msgDlg.SetMarquee(FALSE, 0); |
| | | msgDlg.SetCompleteCode(-1); |
| | | } |
| | | else if (status == SS_COMPLETE) { |
| | | CString strMsg; |
| | | strMsg.Format(_T("è·åé
æ¹å®æï¼")); |
| | | msgDlg.DelayClose(3000); |
| | | msgDlg.SetIcon(MSG_BOX_SUCCEED); |
| | | msgDlg.SetTitle(_T("æä½æå")); |
| | | msgDlg.SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | msgDlg.SetMarquee(FALSE, 0); |
| | | msgDlg.SetCompleteCode(0); |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | FillRecipeListToListCtrl(pRecipeList); |
| | | } |
| | | }); |
| | | // è·åé
æ¹å表 |
| | | CMsgDlg msgDlg("请çå¾
", "æ£å¨è·åé
æ¹å表..."); |
| | | msgDlg.SetData((DWORD_PTR)this); |
| | | msgDlg.SetDataEx((DWORD_PTR)pEq); |
| | | msgDlg.BeginThread(SyncThreadFunction); |
| | | msgDlg.DoModal(); |
| | | } |
| | | } |
| | | |
| | | void CPageRecipe::OnLvnItemChangedListPPID(NMHDR* pNMHDR, LRESULT* pResult) |
| | | void CPageRecipe::OnClickListPPID(NMHDR* pNMHDR, LRESULT* pResult) |
| | | { |
| | | LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); |
| | | LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | *pResult = 0; |
| | | |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); |
| | | int nEqSel = pComboBox->GetCurSel(); |
| | | int selectedCount = ListView_GetSelectedCount(m_listPPID.GetSafeHwnd()); |
| | | if (pComboBox == nullptr) { |
| | | return; |
| | | } |
| | | |
| | | GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0 && selectedCount > 0); |
| | | GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nEqSel == 0 && selectedCount > 0); |
| | | GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && selectedCount > 0); |
| | | GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && selectedCount > 0); |
| | | int nItem = pNMItemActivate->iItem; |
| | | int nEqSel = pComboBox->GetCurSel(); |
| | | |
| | | GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0); |
| | | GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nItem != -1); |
| | | GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && nItem != -1); |
| | | GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && nItem != -1); |
| | | } |
| | | |
| | | void CPageRecipe::OnDblclkListPPID(NMHDR* pNMHDR, LRESULT* pResult) |
| | | { |
| | | LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | *pResult = 0; |
| | | |
| | | int nItem = pNMItemActivate->iItem; |
| | | if (nItem < 0) { |
| | | return; |
| | | } |
| | | |
| | | CString strText = m_listPPID.GetItemText(nItem, 2); |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); |
| | | int nEqSel = pComboBox->GetCurSel(); |
| | | if (nEqSel == CB_ERR) { |
| | | return; |
| | | } |
| | | |
| | | SERVO::CEquipment* pEq = (SERVO::CEquipment*)pComboBox->GetItemDataPtr(nEqSel); |
| | | if (pEq == nullptr) { |
| | | return; |
| | | } |
| | | } |
| | | |
| | | void CPageRecipe::OnCbnSelchangeComboEquipment() |
| | | { |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_EQUIPMENT); |
| | | int nEqSel = pComboBox->GetCurSel(); |
| | | int selectedCount = ListView_GetSelectedCount(m_listPPID.GetSafeHwnd()); |
| | | int nItem = ListView_GetSelectedCount(m_listPPID.GetSafeHwnd()); |
| | | |
| | | GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0 && selectedCount > 0); |
| | | GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nEqSel == 0 && selectedCount > 0); |
| | | GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && selectedCount > 0); |
| | | GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && selectedCount > 0); |
| | | GetDlgItem(IDC_BUTTON_NEW)->EnableWindow(nEqSel == 0); |
| | | GetDlgItem(IDC_BUTTON_MODIFY)->EnableWindow(nEqSel == 0 && nItem != -1); |
| | | GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(nEqSel == 0 && nItem != -1); |
| | | GetDlgItem(IDC_BUTTON_DELETE_ALL)->EnableWindow(nEqSel == 0 && nItem != -1); |
| | | GetDlgItem(IDC_EDIT_KEYWORD)->EnableWindow(nEqSel == 0); |
| | | GetDlgItem(IDC_BUTTON_SEARCH)->EnableWindow(nEqSel == 0); |
| | | |
| | |
| | | } |
| | | else { |
| | | InitListCtrlHeaderForDevice(); |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | FillRecipeListToListCtrl(pRecipeList); |
| | | FillRecipeListToListCtrl(pEq); |
| | | } |
| | | } |
| | | |
| | | UINT CPageRecipe::SyncThreadFunction(LPVOID lpvData) |
| | | { |
| | | CMsgDlg* pMsgDlg = (CMsgDlg*)lpvData; |
| | | CPageRecipe* pPageRecipe = (CPageRecipe*)pMsgDlg->GetData(); |
| | | return pPageRecipe->SyncThreadFunctionInner(pMsgDlg); |
| | | } |
| | | |
| | | UINT CPageRecipe::SyncThreadFunctionInner(CMsgDlg* pMsgDlg) |
| | | { |
| | | SERVO::CEquipment* pEq = (SERVO::CEquipment*)pMsgDlg->GetDataEx(); |
| | | HANDLE hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); |
| | | int nStep = 0; |
| | | |
| | | // åå¤é
æ¹è·¯å¾ |
| | | char szBuffer[_MAX_PATH]; |
| | | sprintf_s(szBuffer, _MAX_PATH, "%s\\Recipe\\EQ%d_Unit0.recipelist", (LPTSTR)(LPCTSTR)theApp.m_strAppDir, pEq->getID()); |
| | | std::string strFilepath(szBuffer); |
| | | |
| | | pEq->masterRecipeListRequest(0, [&, pEq, pMsgDlg, hEvent](int status) -> void { |
| | | Sleep(300); |
| | | if (status == SS_FAILED || status == SS_TIMEOUT) { |
| | | CString strMsg; |
| | | strMsg.Format(status == SS_FAILED ? _T("è·åé
æ¹å表失败ï¼") : _T("è·åé
æ¹å表è¶
æ¶ï¼")); |
| | | pMsgDlg->SetIcon(MSG_BOX_ERROR); |
| | | pMsgDlg->SetTitle(_T("æä½å¤±è´¥")); |
| | | pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | SetEvent(hEvent); |
| | | } |
| | | else if (status == SS_LIST_COMPLETE) { |
| | | CString strMsg; |
| | | strMsg.Format(_T("è·åé
æ¹åè¡¨å®æï¼")); |
| | | pMsgDlg->SetTitle(_T("æä½æå")); |
| | | pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | if (pRecipeList != nullptr && !pRecipeList->getIds().empty()) { |
| | | nStep = 1; |
| | | } |
| | | SetEvent(hEvent); |
| | | } |
| | | }); |
| | | ::WaitForSingleObject(hEvent, INFINITE); |
| | | if (nStep != 1) { |
| | | pEq->saveRecipeList(0, strFilepath); |
| | | pMsgDlg->SetIcon(MSG_BOX_SUCCEED); |
| | | pMsgDlg->SetMarquee(FALSE, 0); |
| | | pMsgDlg->SetCompleteCode(-1); |
| | | pMsgDlg->DelayClose(3000); |
| | | } |
| | | ResetEvent(hEvent); |
| | | |
| | | |
| | | // åæ°å表 |
| | | if (nStep == 1) { |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | ASSERT(pRecipeList); |
| | | auto& ids = pRecipeList->getIds(); |
| | | pMsgDlg->SetTitle(_T("æ£å¨è·ååæ°")); |
| | | for (auto item : ids) { |
| | | int recipeId = item.second; |
| | | CString strMsg; |
| | | strMsg.Format(_T("æ£å¨è·åé
æ¹ %d åæ°..."), item.second); |
| | | pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | pEq->recipeParameterRequest(0, recipeId, 0, [&, pEq, pMsgDlg, recipeId, hEvent](int status) -> void { |
| | | Sleep(500); |
| | | if (status == SS_FAILED || status == SS_TIMEOUT) { |
| | | CString strMsg; |
| | | strMsg.Format(status == SS_FAILED ? _T("è·åé
æ¹ %d åæ°å¤±è´¥ï¼") : _T("è·åé
æ¹ %d åæ°è¶
æ¶ï¼"), recipeId); |
| | | pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | |
| | | Sleep(30); |
| | | SetEvent(hEvent); |
| | | } |
| | | else if (status == SS_PARAMS_COMPLETE) { |
| | | CString strMsg; |
| | | strMsg.Format(_T("è·åé
æ¹ %d 忰宿ï¼"), item.second); |
| | | pMsgDlg->SetMessage((LPTSTR)(LPCTSTR)strMsg); |
| | | |
| | | Sleep(30); |
| | | SetEvent(hEvent); |
| | | } |
| | | }); |
| | | ::WaitForSingleObject(hEvent, INFINITE); |
| | | ResetEvent(hEvent); |
| | | } |
| | | |
| | | |
| | | pEq->saveRecipeList(0, strFilepath); |
| | | pMsgDlg->SetIcon(MSG_BOX_SUCCEED); |
| | | pMsgDlg->SetTitle(_T("æä½å®æ")); |
| | | pMsgDlg->SetCompleteCode(0); |
| | | pMsgDlg->SetMarquee(FALSE, 0); |
| | | pMsgDlg->DelayClose(3000); |
| | | }; |
| | | |
| | | FillRecipeListToListCtrl(pEq); |
| | | CloseHandle(hEvent); |
| | | |
| | | |
| | | // 卿¤æå°é
æ¹åæ°ä»¥ä¾¿æ ¸å¯¹æ°æ® |
| | | SERVO::CRecipeList* pRecipeList = pEq->getRecipeList(0); |
| | | ASSERT(pRecipeList); |
| | | auto rawDatas = pRecipeList->getParamsRawData(); |
| | | for (auto item : rawDatas) { |
| | | TRACE("================= é
æ¹ %d\n", item.first); |
| | | |
| | | std::vector<CParam> params; |
| | | pEq->parsingParams((const char*)item.second.data(), item.second.size(), params); |
| | | for (auto p : params) { |
| | | if (p.getValueType() == PVT_INT) { |
| | | TRACE("%s: %d\n", p.getName().c_str(), p.getIntValue()); |
| | | } |
| | | else if (p.getValueType() == PVT_DOUBLE) { |
| | | TRACE("%s: %f\n", p.getName().c_str(), p.getDoubleValue()); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | |
| | | #include "afxdialogex.h" |
| | | #include "RecipeManager.h" |
| | | #include "ListCtrlEx.h" |
| | | #include "MsgDlg.h" |
| | | |
| | | |
| | | // CPageRecipe å¯¹è¯æ¡ |
| | | |
| | |
| | | CPageRecipe(CWnd* pParent = nullptr); // æ åæé 彿° |
| | | virtual ~CPageRecipe(); |
| | | |
| | | public: |
| | | static UINT SyncThreadFunction(LPVOID lpvData); |
| | | UINT SyncThreadFunctionInner(CMsgDlg* pMsgDlg); |
| | | |
| | | private: |
| | | void InitListCtrlHeaderForMaster(); |
| | | void InitListCtrlHeaderForDevice(); |
| | | void UpdateRecipeByPPID(const CString& strPPID); |
| | | void FillDataToListCtrl(const std::vector<RecipeInfo>& vecRecipe); |
| | | void FillRecipeListToListCtrl(SERVO::CRecipeList* pList); |
| | | void FillRecipeListToListCtrl(SERVO::CEquipment* pEq); |
| | | |
| | | // å¯¹è¯æ¡æ°æ® |
| | | #ifdef AFX_DESIGN_TIME |
| | |
| | | afx_msg void OnBnClickedButtonDelete(); |
| | | afx_msg void OnBnClickedButtonDeleteAll(); |
| | | afx_msg void OnBnClickedButtonRefresh(); |
| | | afx_msg void OnLvnItemChangedListPPID(NMHDR* pNMHDR, LRESULT* pResult); |
| | | afx_msg void OnClickListPPID(NMHDR* pNMHDR, LRESULT* pResult); |
| | | afx_msg void OnDblclkListPPID(NMHDR* pNMHDR, LRESULT* pResult); |
| | | afx_msg void OnCbnSelchangeComboEquipment(); |
| | | DECLARE_MESSAGE_MAP() |
| | | |
| | | private: |
| | | CListCtrlEx m_listPPID; |
| | | }; |
| | | }; |
| | |
| | | #include "RecipeManager.h" |
| | | #include "ServoCommo.h" |
| | | |
| | | |
| | | |
| | | #define CHECKBOX_ALL_ID 0x1234 |
| | | |
| | | // CPortConfigurationDlg å¯¹è¯æ¡ |
| | |
| | | // åå¡« Job ä¿¡æ¯ï¼åªå第ä¸ä¸ªææ Glassï¼ |
| | | if (!bJobInfoSet && pGlass) { |
| | | SERVO::CJobDataS* pJS = pGlass->getJobDataS(); |
| | | if (pJS) { |
| | | if (pJS) { |
| | | int nRecipeID = pJobDataS->getMasterRecipe(); |
| | | std::string strRecipeName = RecipeManager::getInstance().getPPIDById(nRecipeID); |
| | | SetDlgItemText(IDC_EDIT_LOTID, CString(pJS->getLotId().c_str())); |
| | | SetDlgItemText(IDC_EDIT_PRODUCTID, CString(pJS->getProductId().c_str())); |
| | | SetDlgItemText(IDC_EDIT_OPERATIONID, CString(pJS->getOperationId().c_str())); |
| | | m_comboMaterialsType.SetCurSel(pJS->getMaterialsType() - 1); |
| | | |
| | | if (!strRecipeName.empty()) { |
| | | CString csRecipeName(strRecipeName.c_str()); |
| | | int nIndex = m_comboRecipe.FindStringExact(-1, csRecipeName); |
| | | if (nIndex != CB_ERR) { |
| | | m_comboRecipe.SetCurSel(nIndex); |
| | | } |
| | | else { |
| | | AfxMessageBox(_T("å½åé
æ¹å¨ç³»ç»ä¸ä¸åå¨ï¼è¯·éæ°éæ©ï¼"), MB_ICONWARNING); |
| | | m_comboRecipe.SetCurSel(0); |
| | | } |
| | | } |
| | | |
| | | bJobInfoSet = true; |
| | | } |
| | | } |
| | |
| | | SetWindowText(_T("Port Configuration")); |
| | | } |
| | | |
| | | |
| | | // Porcess Start / Process Cancel æé®ç¶æ |
| | | GetDlgItem(IDC_BUTTON_PROCESS_START)->EnableWindow(FALSE); |
| | | GetDlgItem(IDC_BUTTON_PROCESS_CANCEL)->EnableWindow(FALSE); |
| | |
| | | m_comboRecipe.GetLBText(selRecipe, str); |
| | | config.strRecipe = CT2A(str.GetString()); |
| | | } |
| | | int nRecipeID = RecipeManager::getInstance().getIdByPPID(config.strRecipe); |
| | | RecipeInfo stRecipeInfo = RecipeManager::getInstance().getRecipeByPPID(config.strRecipe); |
| | | std::vector<DeviceRecipe> vecRecipeInfo = stRecipeInfo.vecDeviceList; |
| | | |
| | | // è·å Material Type ç´¢å¼ï¼ç´¢å¼ä» 0 å¼å§ï¼å¯¹åºæä¸¾ä» 1 å¼å§ï¼ |
| | | //int selMaterial = m_comboMaterialsType.GetCurSel(); |
| | |
| | | CGridCellCombo* pCombo = dynamic_cast<CGridCellCombo*>(m_wndGrid.GetCell(i, 2)); |
| | | ASSERT(pCheck && pCombo); |
| | | pGlass->setScheduledForProcessing(pCheck->GetCheck()); |
| | | /*pGlass->setType(static_cast<SERVO::MaterialsType>(config.nMaterialType));*/ |
| | | pGlass->setType(static_cast<SERVO::MaterialsType>(nMaterialType)); |
| | | |
| | | 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(nMaterialType); |
| | | |
| | | RecipeInfo stRecipeInfo = RecipeManager::getInstance().getRecipeByPPID(config.strRecipe); |
| | | std::vector<DeviceRecipe> vecRecipeInfo = stRecipeInfo.vecDeviceList; |
| | | pJobDataS->setMasterRecipe(nRecipeID); |
| | | |
| | | for (const auto& info : vecRecipeInfo) { |
| | | const std::string& name = info.strDeviceName; |
| | |
| | | |
| | | // ç»å®çé¢éè¦æ¾ç¤ºçè®¾å¤ |
| | | static const std::vector<DeviceMetaInfo> g_vecBindDevices = { |
| | | { EQ_ID_VACUUMBAKE, EQ_NAME_VACUUMBAKE }, |
| | | { EQ_ID_Bonder1, EQ_NAME_BONDER1 }, |
| | | { EQ_ID_Bonder2, EQ_NAME_BONDER2 }, |
| | | { EQ_ID_BAKE_COOLING, EQ_NAME_BAKE_COOLING }, |
| | | { EQ_ID_MEASUREMENT, EQ_NAME_MEASUREMENT }, |
| | | { EQ_ID_EFEM, EQ_NAME_EFEM } |
| | | { EQ_ID_VACUUMBAKE, EQ_NAME_VACUUMBAKE }, |
| | | { EQ_ID_Bonder1, EQ_NAME_BONDER1 }, |
| | | { EQ_ID_Bonder2, EQ_NAME_BONDER2 }, |
| | | { EQ_ID_BAKE_COOLING, EQ_NAME_BAKE_COOLING }, |
| | | { EQ_ID_MEASUREMENT, EQ_NAME_MEASUREMENT }, |
| | | { EQ_ID_EFEM, EQ_NAME_EFEM } |
| | | }; |
| | | |
| | | // CRecipeDeviceBindDlg å¯¹è¯æ¡ |
| | |
| | | |
| | | CRecipeDeviceBindDlg::CRecipeDeviceBindDlg(CWnd* pParent /*=nullptr*/) |
| | | : CDialogEx(IDD_DIALOG_RECIPE_DEVICE_BIND, pParent) |
| | | , m_strPPID(_T("")) |
| | | , m_strDesc(_T("")) |
| | | , m_strPPID(_T("")) |
| | | , m_strDesc(_T("")) |
| | | { |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | const RecipeInfo& CRecipeDeviceBindDlg::GetRecipeInfo() const { |
| | | return m_recipe; |
| | | return m_recipe; |
| | | } |
| | | |
| | | void CRecipeDeviceBindDlg::SetRecipeInfo(const RecipeInfo& info) |
| | | { |
| | | m_recipe = info; |
| | | m_recipe = info; |
| | | } |
| | | |
| | | void CRecipeDeviceBindDlg::ReleaseDeviceControls() |
| | | { |
| | | for (auto& ctrl : m_vecDevices) { |
| | | delete ctrl.editDeviceID; ctrl.editDeviceID = nullptr; |
| | | delete ctrl.editDeviceName; ctrl.editDeviceName = nullptr; |
| | | delete ctrl.comboRecipeID; ctrl.comboRecipeID = nullptr; |
| | | } |
| | | m_vecDevices.clear(); |
| | | for (auto& ctrl : m_vecDevices) { |
| | | delete ctrl.editDeviceID; ctrl.editDeviceID = nullptr; |
| | | delete ctrl.editDeviceName; ctrl.editDeviceName = nullptr; |
| | | delete ctrl.comboRecipeID; ctrl.comboRecipeID = nullptr; |
| | | } |
| | | m_vecDevices.clear(); |
| | | } |
| | | |
| | | void CRecipeDeviceBindDlg::CreateDeviceControls(int nXStart, int nYStart, int nTotalControlWidth, int nRowHeight) |
| | | { |
| | | for (size_t i = 0; i < g_vecBindDevices.size(); ++i) { |
| | | int y = nYStart + static_cast<int>(i) * nRowHeight; |
| | | auto* pEditID = new CEdit; |
| | | pEditID->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER, CRect(nXStart, y, nXStart + 100, y + 25), this, (UINT)(IDC_EDIT_DEVICEID_BASE + i)); |
| | | pEditID->SetFont(&m_font); |
| | | for (size_t i = 0; i < g_vecBindDevices.size(); ++i) { |
| | | int y = nYStart + static_cast<int>(i) * nRowHeight; |
| | | auto* pEditID = new CEdit; |
| | | pEditID->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER, CRect(nXStart, y, nXStart + 100, y + 25), this, (UINT)(IDC_EDIT_DEVICEID_BASE + i)); |
| | | pEditID->SetFont(&m_font); |
| | | |
| | | auto* pEditName = new CEdit; |
| | | pEditName->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER, CRect(nXStart + 110, y, nXStart + 210, y + 25), this, (UINT)(IDC_EDIT_DEVICENAME_BASE + i)); |
| | | pEditName->SetFont(&m_font); |
| | | auto* pEditName = new CEdit; |
| | | pEditName->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER, CRect(nXStart + 110, y, nXStart + 210, y + 25), this, (UINT)(IDC_EDIT_DEVICENAME_BASE + i)); |
| | | pEditName->SetFont(&m_font); |
| | | |
| | | auto* pCombo = new CComboBox; |
| | | pCombo->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, CRect(nXStart + 220, y, nXStart + nTotalControlWidth, y + 25), this, (UINT)(IDC_COMBO_RECIPEID_BASE + i)); |
| | | pCombo->SetFont(&m_font); |
| | | auto* pCombo = new CComboBox; |
| | | pCombo->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, CRect(nXStart + 220, y, nXStart + nTotalControlWidth, y + 25), this, (UINT)(IDC_COMBO_RECIPEID_BASE + i)); |
| | | pCombo->SetFont(&m_font); |
| | | |
| | | m_vecDevices.push_back({ pEditID, pEditName, pCombo }); |
| | | } |
| | | m_vecDevices.push_back({ pEditID, pEditName, pCombo }); |
| | | } |
| | | } |
| | | |
| | | bool CRecipeDeviceBindDlg::FillComboRecipeList(CComboBox* pCombo, int nDeviceID, int nSelectedRecipeID) |
| | | { |
| | | auto& master = theApp.m_model.getMaster(); |
| | | auto* pEq = master.getEquipment(nDeviceID); |
| | | if (!pEq) { |
| | | return false; |
| | | } |
| | | auto& master = theApp.m_model.getMaster(); |
| | | auto* pEq = master.getEquipment(nDeviceID); |
| | | if (!pEq) { |
| | | return false; |
| | | } |
| | | |
| | | auto* pRecipeList = pEq->getRecipeList(0); |
| | | if (!pRecipeList) { |
| | | return false; |
| | | } |
| | | auto* pRecipeList = pEq->getRecipeList(0); |
| | | if (!pRecipeList) { |
| | | return false; |
| | | } |
| | | |
| | | auto& mapRecipeIds = pRecipeList->getIds(); |
| | | bool bFound = false; |
| | | pCombo->ResetContent(); |
| | | for (const auto& pair : mapRecipeIds) { |
| | | int nRecipeID = pair.second; |
| | | CString strRecipeName; |
| | | strRecipeName.Format(_T("%d"), nRecipeID); |
| | | int idx = pCombo->AddString(strRecipeName); |
| | | pCombo->SetItemData(idx, nRecipeID); |
| | | if (nSelectedRecipeID == nRecipeID) { |
| | | pCombo->SetCurSel(idx); |
| | | bFound = true; |
| | | } |
| | | } |
| | | auto& mapRecipeIds = pRecipeList->getIds(); |
| | | bool bFound = false; |
| | | pCombo->ResetContent(); |
| | | for (const auto& pair : mapRecipeIds) { |
| | | int nRecipeID = pair.second; |
| | | |
| | | if (nSelectedRecipeID != -1 && !bFound) { |
| | | pCombo->SetCurSel(CB_ERR); |
| | | } |
| | | else if (pCombo->GetCount() > 0 && nSelectedRecipeID == -1) { |
| | | pCombo->SetCurSel(0); |
| | | } |
| | | std::string strRecipeName = RecipeManager::getInstance().getDeviceRecipeName(pEq->getName(), nRecipeID); |
| | | if (strRecipeName.empty()) { |
| | | strRecipeName = std::to_string(nRecipeID); |
| | | } |
| | | |
| | | return true; |
| | | CString str; |
| | | str.Format(_T("%s"), strRecipeName.c_str()); |
| | | int idx = pCombo->AddString(str); |
| | | pCombo->SetItemData(idx, nRecipeID); |
| | | if (nSelectedRecipeID == nRecipeID) { |
| | | pCombo->SetCurSel(idx); |
| | | bFound = true; |
| | | } |
| | | } |
| | | |
| | | if (nSelectedRecipeID != -1 && !bFound) { |
| | | pCombo->SetCurSel(CB_ERR); |
| | | } |
| | | else if (pCombo->GetCount() > 0 && nSelectedRecipeID == -1) { |
| | | pCombo->SetCurSel(0); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | bool CRecipeDeviceBindDlg::FillDeviceInfo(int idx, int nDeviceID, const CString& strDeviceName, int nSelectedRecipeID) |
| | | { |
| | | if (idx < 0 || idx >= (int)m_vecDevices.size()) { |
| | | return false; |
| | | } |
| | | if (idx < 0 || idx >= (int)m_vecDevices.size()) { |
| | | return false; |
| | | } |
| | | |
| | | auto& ctrl = m_vecDevices[idx]; |
| | | CString strID; |
| | | strID.Format(_T("%d"), nDeviceID); |
| | | ctrl.editDeviceID->SetWindowText(strID); |
| | | ctrl.editDeviceID->SetReadOnly(TRUE); |
| | | ctrl.editDeviceName->SetWindowText(strDeviceName); |
| | | ctrl.editDeviceName->SetReadOnly(TRUE); |
| | | auto& ctrl = m_vecDevices[idx]; |
| | | CString strID; |
| | | strID.Format(_T("%d"), nDeviceID); |
| | | ctrl.editDeviceID->SetWindowText(strID); |
| | | ctrl.editDeviceID->SetReadOnly(TRUE); |
| | | ctrl.editDeviceName->SetWindowText(strDeviceName); |
| | | ctrl.editDeviceName->SetReadOnly(TRUE); |
| | | |
| | | if (!FillComboRecipeList(ctrl.comboRecipeID, nDeviceID, nSelectedRecipeID)) { |
| | | CString str; |
| | | str.Format(_T("è®¾å¤ [%s] æå
¶é
æ¹åè¡¨æªæ¾å°ï¼è¯·æ£æ¥è®¾å¤é
ç½®"), strDeviceName.GetString()); |
| | | AfxMessageBox(str); |
| | | return false; |
| | | } |
| | | return true; |
| | | if (!FillComboRecipeList(ctrl.comboRecipeID, nDeviceID, nSelectedRecipeID)) { |
| | | CString str; |
| | | str.Format(_T("è®¾å¤ [%s] æå
¶é
æ¹åè¡¨æªæ¾å°ï¼è¯·æ£æ¥è®¾å¤é
ç½®"), strDeviceName.GetString()); |
| | | AfxMessageBox(str); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | void CRecipeDeviceBindDlg::DoDataExchange(CDataExchange* pDX) |
| | | { |
| | | CDialogEx::DoDataExchange(pDX); |
| | | DDX_Text(pDX, IDC_EDIT_PPID, m_strPPID); |
| | | DDX_Text(pDX, IDC_EDIT_DESC, m_strDesc); |
| | | CDialogEx::DoDataExchange(pDX); |
| | | DDX_Text(pDX, IDC_EDIT_PPID, m_strPPID); |
| | | DDX_Text(pDX, IDC_EDIT_DESC, m_strDesc); |
| | | } |
| | | |
| | | BEGIN_MESSAGE_MAP(CRecipeDeviceBindDlg, CDialogEx) |
| | | ON_WM_CLOSE() |
| | | ON_WM_SIZE() |
| | | ON_BN_CLICKED(IDOK, &CRecipeDeviceBindDlg::OnBnClickedOk) |
| | | ON_WM_CLOSE() |
| | | ON_WM_SIZE() |
| | | ON_BN_CLICKED(IDOK, &CRecipeDeviceBindDlg::OnBnClickedOk) |
| | | END_MESSAGE_MAP() |
| | | |
| | | |
| | |
| | | CDialogEx::OnInitDialog(); |
| | | |
| | | // è®¾ç½®å¯¹è¯æ¡æ é¢ |
| | | SetWindowText(m_recipe.vecDeviceList.empty() ? _T("æ°å»ºé
æ¹") : _T("ç¼è¾é
æ¹")); |
| | | SetWindowText(m_recipe.vecDeviceList.empty() ? _T("æ°å»ºé
æ¹") : _T("ç¼è¾é
æ¹")); |
| | | |
| | | // åå»ºå¨ææ§ä»¶åä½ |
| | | if (!m_font.m_hObject) { |
| | | CFont* pDlgFont = GetFont(); |
| | | LOGFONT lf; |
| | | if (pDlgFont && pDlgFont->GetLogFont(&lf)) { |
| | | lf.lfHeight = -16; |
| | | m_font.CreateFontIndirect(&lf); |
| | | } |
| | | } |
| | | if (!m_font.m_hObject) { |
| | | CFont* pDlgFont = GetFont(); |
| | | LOGFONT lf; |
| | | if (pDlgFont && pDlgFont->GetLogFont(&lf)) { |
| | | lf.lfHeight = -16; |
| | | m_font.CreateFontIndirect(&lf); |
| | | } |
| | | } |
| | | |
| | | // 计ç®åæ |
| | | CRect rDesc; |
| | | int nXStart = 30, nYStart = 30, nTotalControlWidth = 340; |
| | | if (auto* pWndDesc = GetDlgItem(IDC_STATIC_DESC)) { |
| | | pWndDesc->GetWindowRect(&rDesc); ScreenToClient(&rDesc); |
| | | nXStart = rDesc.left; |
| | | } |
| | | if (auto* pWndEdit = GetDlgItem(IDC_EDIT_DESC)) { |
| | | pWndEdit->GetWindowRect(&rDesc); ScreenToClient(&rDesc); |
| | | nYStart = rDesc.bottom + 20; |
| | | } |
| | | CRect rClient; GetClientRect(&rClient); |
| | | nTotalControlWidth = rClient.Width() - nXStart * 2; |
| | | const int nRowHeight = 30; |
| | | // 计ç®åæ |
| | | CRect rDesc; |
| | | int nXStart = 30, nYStart = 30, nTotalControlWidth = 340; |
| | | if (auto* pWndDesc = GetDlgItem(IDC_STATIC_DESC)) { |
| | | pWndDesc->GetWindowRect(&rDesc); ScreenToClient(&rDesc); |
| | | nXStart = rDesc.left; |
| | | } |
| | | if (auto* pWndEdit = GetDlgItem(IDC_EDIT_DESC)) { |
| | | pWndEdit->GetWindowRect(&rDesc); ScreenToClient(&rDesc); |
| | | nYStart = rDesc.bottom + 20; |
| | | } |
| | | CRect rClient; GetClientRect(&rClient); |
| | | nTotalControlWidth = rClient.Width() - nXStart * 2; |
| | | const int nRowHeight = 30; |
| | | |
| | | // æ¸
ç©ºæ§æ§ä»¶ |
| | | ReleaseDeviceControls(); |
| | | // æ¸
ç©ºæ§æ§ä»¶ |
| | | ReleaseDeviceControls(); |
| | | |
| | | // åå»ºæ°æ§ä»¶ |
| | | CreateDeviceControls(nXStart, nYStart, nTotalControlWidth, nRowHeight); |
| | | // åå»ºæ°æ§ä»¶ |
| | | CreateDeviceControls(nXStart, nYStart, nTotalControlWidth, nRowHeight); |
| | | |
| | | auto& master = theApp.m_model.getMaster(); |
| | | auto& master = theApp.m_model.getMaster(); |
| | | |
| | | // å¡«å
å
容 |
| | | if (m_recipe.vecDeviceList.empty()) { |
| | | // æ°å»º |
| | | for (size_t i = 0; i < g_vecBindDevices.size(); ++i) { |
| | | const auto& meta = g_vecBindDevices[i]; |
| | | FillDeviceInfo((int)i, meta.nDeviceID, meta.strDeviceName); |
| | | } |
| | | } |
| | | else { |
| | | // ç¼è¾ |
| | | m_strPPID = CA2T(m_recipe.strPPID.c_str()); |
| | | m_strDesc = CA2T(m_recipe.strDescription.c_str()); |
| | | UpdateData(FALSE); |
| | | // å¡«å
å
容 |
| | | if (m_recipe.vecDeviceList.empty()) { |
| | | // æ°å»º |
| | | for (size_t i = 0; i < g_vecBindDevices.size(); ++i) { |
| | | const auto& meta = g_vecBindDevices[i]; |
| | | FillDeviceInfo((int)i, meta.nDeviceID, meta.strDeviceName); |
| | | } |
| | | } |
| | | else { |
| | | // ç¼è¾ |
| | | m_strPPID = CA2T(m_recipe.strPPID.c_str()); |
| | | m_strDesc = CA2T(m_recipe.strDescription.c_str()); |
| | | UpdateData(FALSE); |
| | | |
| | | for (size_t i = 0; i < m_recipe.vecDeviceList.size() && i < m_vecDevices.size(); ++i) { |
| | | const auto& d = m_recipe.vecDeviceList[i]; |
| | | FillDeviceInfo((int)i, d.nDeviceID, d.strDeviceName.c_str(), d.nRecipeID); |
| | | } |
| | | } |
| | | for (size_t i = 0; i < m_recipe.vecDeviceList.size() && i < m_vecDevices.size(); ++i) { |
| | | const auto& d = m_recipe.vecDeviceList[i]; |
| | | FillDeviceInfo((int)i, d.nDeviceID, d.strDeviceName.c_str(), d.nRecipeID); |
| | | } |
| | | } |
| | | |
| | | CenterWindow(); |
| | | CenterWindow(); |
| | | |
| | | return TRUE; // return TRUE unless you set the focus to a control |
| | | // å¼å¸¸: OCX 屿§é¡µåºè¿å FALSE |
| | |
| | | |
| | | void CRecipeDeviceBindDlg::OnClose() |
| | | { |
| | | // TODO: 卿¤æ·»å æ¶æ¯å¤çç¨åºä»£ç å/æè°ç¨é»è®¤å¼ |
| | | CDialogEx::OnClose(); |
| | | // TODO: 卿¤æ·»å æ¶æ¯å¤çç¨åºä»£ç å/æè°ç¨é»è®¤å¼ |
| | | CDialogEx::OnClose(); |
| | | |
| | | // æ¸
çæ§ä»¶ |
| | | ReleaseDeviceControls(); |
| | | // æ¸
çæ§ä»¶ |
| | | ReleaseDeviceControls(); |
| | | } |
| | | |
| | | void CRecipeDeviceBindDlg::OnSize(UINT nType, int cx, int cy) |
| | | { |
| | | CDialogEx::OnSize(nType, cx, cy); |
| | | CDialogEx::OnSize(nType, cx, cy); |
| | | |
| | | // TODO: 卿¤å¤æ·»å æ¶æ¯å¤çç¨åºä»£ç |
| | | // TODO: 卿¤å¤æ·»å æ¶æ¯å¤çç¨åºä»£ç |
| | | } |
| | | |
| | | void CRecipeDeviceBindDlg::OnBnClickedOk() |
| | | { |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | UpdateData(TRUE); |
| | | // TODO: 卿¤æ·»å æ§ä»¶éç¥å¤çç¨åºä»£ç |
| | | UpdateData(TRUE); |
| | | |
| | | // æ¶éææè®¾å¤æ å° |
| | | m_recipe.vecDeviceList.clear(); |
| | | for (const auto& dev : m_vecDevices) { |
| | | DeviceRecipe info; |
| | | CString strID, strName; |
| | | dev.editDeviceID->GetWindowText(strID); |
| | | dev.editDeviceName->GetWindowText(strName); |
| | | // æ¶éææè®¾å¤æ å° |
| | | m_recipe.vecDeviceList.clear(); |
| | | for (const auto& dev : m_vecDevices) { |
| | | DeviceRecipe info; |
| | | CString strID, strName; |
| | | dev.editDeviceID->GetWindowText(strID); |
| | | dev.editDeviceName->GetWindowText(strName); |
| | | |
| | | int sel = dev.comboRecipeID->GetCurSel(); |
| | | info.nRecipeID = -1; |
| | | if (sel != CB_ERR) { |
| | | info.nRecipeID = (int)dev.comboRecipeID->GetItemData(sel); |
| | | } |
| | | info.nDeviceID = _ttoi(strID); |
| | | info.strDeviceName = CT2A(strName); |
| | | int sel = dev.comboRecipeID->GetCurSel(); |
| | | info.nRecipeID = -1; |
| | | if (sel != CB_ERR) { |
| | | info.nRecipeID = (int)dev.comboRecipeID->GetItemData(sel); |
| | | } |
| | | info.nDeviceID = _ttoi(strID); |
| | | info.strDeviceName = CT2A(strName); |
| | | |
| | | m_recipe.vecDeviceList.push_back(info); |
| | | } |
| | | m_recipe.vecDeviceList.push_back(info); |
| | | } |
| | | |
| | | // æ£æ¥ PPID æ¯å¦ä¸ºç©º |
| | | if (m_strPPID.IsEmpty()) { |
| | | AfxMessageBox(_T("é
æ¹ PPID ä¸è½ä¸ºç©º")); |
| | | return; |
| | | } |
| | | // æ£æ¥ PPID æ¯å¦ä¸ºç©º |
| | | if (m_strPPID.IsEmpty()) { |
| | | AfxMessageBox(_T("é
æ¹ PPID ä¸è½ä¸ºç©º")); |
| | | return; |
| | | } |
| | | |
| | | // PPIDåæè¿° |
| | | m_recipe.strPPID = CT2A(m_strPPID); |
| | | m_recipe.strDescription = CT2A(m_strDesc); |
| | | // PPIDåæè¿° |
| | | m_recipe.strPPID = CT2A(m_strPPID); |
| | | m_recipe.strDescription = CT2A(m_strDesc); |
| | | |
| | | CDialogEx::OnOK(); |
| | | CDialogEx::OnOK(); |
| | | } |
| | |
| | | #include "stdafx.h" |
| | | #include "stdafx.h" |
| | | #include "RecipeManager.h" |
| | | #include <sstream> |
| | | #include <iomanip> |
| | |
| | | std::recursive_mutex RecipeManager::m_mutex; |
| | | |
| | | RecipeManager& RecipeManager::getInstance() { |
| | | static RecipeManager instance; |
| | | return instance; |
| | | static RecipeManager instance; |
| | | return instance; |
| | | } |
| | | |
| | | RecipeManager::RecipeManager() { |
| | | m_pDB = new BL::SQLiteDatabase(); |
| | | m_pDB = new BL::SQLiteDatabase(); |
| | | } |
| | | |
| | | RecipeManager::~RecipeManager() { |
| | | if (m_pDB) { |
| | | delete m_pDB; |
| | | m_pDB = nullptr; |
| | | } |
| | | if (m_pDB) { |
| | | delete m_pDB; |
| | | m_pDB = nullptr; |
| | | } |
| | | } |
| | | |
| | | bool RecipeManager::initRecipeTable() { |
| | | char szPath[MAX_PATH]; |
| | | GetModuleFileNameA(NULL, szPath, MAX_PATH); |
| | | std::string exePath(szPath); |
| | | std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB"; |
| | | CreateDirectoryA(dbDir.c_str(), NULL); |
| | | char szPath[MAX_PATH]; |
| | | GetModuleFileNameA(NULL, szPath, MAX_PATH); |
| | | std::string exePath(szPath); |
| | | std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB"; |
| | | CreateDirectoryA(dbDir.c_str(), NULL); |
| | | |
| | | std::string dbPath = dbDir + "\\RecipeManager.db"; |
| | | if (!m_pDB->connect(dbPath, true)) { |
| | | return false; |
| | | } |
| | | std::string dbPath = dbDir + "\\RecipeManager.db"; |
| | | if (!m_pDB->connect(dbPath, true)) { |
| | | return false; |
| | | } |
| | | |
| | | // å¯ç¨ SQLite çå¤é®çº¦ææ¯æ |
| | | if (!m_pDB->executeQuery("PRAGMA foreign_keys = ON;")) { |
| | | std::cerr << "Failed to enable foreign keys." << std::endl; |
| | | return false; |
| | | } |
| | | // å¯ç¨ SQLite çå¤é®çº¦ææ¯æ |
| | | if (!m_pDB->executeQuery("PRAGMA foreign_keys = ON;")) { |
| | | std::cerr << "Failed to enable foreign keys." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | const std::string createRecipeTable = R"( |
| | | CREATE TABLE IF NOT EXISTS recipes ( |
| | | ppid TEXT PRIMARY KEY NOT NULL, |
| | | description TEXT, |
| | | create_time TEXT DEFAULT (datetime('now', 'localtime')) |
| | | ); |
| | | )"; |
| | | const std::string createRecipeTable = R"( |
| | | CREATE TABLE IF NOT EXISTS recipes ( |
| | | id INTEGER PRIMARY KEY AUTOINCREMENT, |
| | | ppid TEXT NOT NULL UNIQUE, |
| | | description TEXT, |
| | | create_time TEXT DEFAULT (datetime('now', 'localtime')) |
| | | ); |
| | | )"; |
| | | |
| | | const std::string createDeviceTable = R"( |
| | | CREATE TABLE IF NOT EXISTS recipe_devices ( |
| | | id INTEGER PRIMARY KEY AUTOINCREMENT, |
| | | ppid TEXT NOT NULL, |
| | | device_id INTEGER NOT NULL, |
| | | device_name TEXT NOT NULL, |
| | | recipe_id INTEGER NOT NULL, |
| | | FOREIGN KEY(ppid) REFERENCES recipes(ppid) ON DELETE CASCADE ON UPDATE CASCADE, |
| | | UNIQUE (ppid, device_id), |
| | | UNIQUE (ppid, device_name) |
| | | ); |
| | | )"; |
| | | const std::string createDeviceTable = R"( |
| | | CREATE TABLE IF NOT EXISTS recipe_devices ( |
| | | id INTEGER PRIMARY KEY AUTOINCREMENT, |
| | | ppid TEXT NOT NULL, |
| | | device_id INTEGER NOT NULL, |
| | | device_name TEXT NOT NULL, |
| | | recipe_id INTEGER NOT NULL, |
| | | recipe_name TEXT NOT NULL, |
| | | FOREIGN KEY(ppid) REFERENCES recipes(ppid) ON DELETE CASCADE ON UPDATE CASCADE, |
| | | UNIQUE (ppid, device_id), |
| | | UNIQUE (ppid, device_name) |
| | | ); |
| | | )"; |
| | | |
| | | return m_pDB->executeQuery(createRecipeTable) && m_pDB->executeQuery(createDeviceTable); |
| | | return m_pDB->executeQuery(createRecipeTable) && m_pDB->executeQuery(createDeviceTable); |
| | | } |
| | | |
| | | void RecipeManager::termRecipeTable() { |
| | | if (!m_pDB) { |
| | | return; |
| | | } |
| | | if (!m_pDB) { |
| | | return; |
| | | } |
| | | |
| | | m_pDB->disconnect(); |
| | | m_pDB->disconnect(); |
| | | } |
| | | |
| | | bool RecipeManager::destroyRecipeTable() { |
| | | if (!m_pDB) { |
| | | if (!m_pDB) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return m_pDB->executeQuery("DROP TABLE IF EXISTS recipe_devices;") && m_pDB->executeQuery("DROP TABLE IF EXISTS recipes;"); |
| | | return m_pDB->executeQuery("DROP TABLE IF EXISTS recipe_devices;") && m_pDB->executeQuery("DROP TABLE IF EXISTS recipes;"); |
| | | } |
| | | |
| | | bool RecipeManager::ppidExists(const std::string& ppid) { |
| | | std::ostringstream oss; |
| | | oss << "SELECT COUNT(*) FROM recipes WHERE ppid = '" << ppid << "';"; |
| | | auto result = m_pDB->fetchResults(oss.str()); |
| | | return (!result.empty() && !result[0].empty() && result[0][0] != "0"); |
| | | std::ostringstream oss; |
| | | oss << "SELECT COUNT(*) FROM recipes WHERE ppid = '" << ppid << "';"; |
| | | auto result = m_pDB->fetchResults(oss.str()); |
| | | return (!result.empty() && !result[0].empty() && result[0][0] != "0"); |
| | | } |
| | | |
| | | bool RecipeManager::deviceExists(const std::string& ppid, int nDeviceID) { |
| | | std::ostringstream oss; |
| | | oss << "SELECT COUNT(*) FROM recipe_devices WHERE ppid = '" << ppid |
| | | << "' AND device_id = " << nDeviceID << ";"; |
| | | auto result = m_pDB->fetchResults(oss.str()); |
| | | return (!result.empty() && !result[0].empty() && result[0][0] != "0"); |
| | | std::ostringstream oss; |
| | | oss << "SELECT COUNT(*) FROM recipe_devices WHERE ppid = '" << ppid |
| | | << "' AND device_id = " << nDeviceID << ";"; |
| | | auto result = m_pDB->fetchResults(oss.str()); |
| | | return (!result.empty() && !result[0].empty() && result[0][0] != "0"); |
| | | } |
| | | |
| | | bool RecipeManager::addRecipe(const RecipeInfo& recipe) { |
| | | if (!m_pDB || recipe.strPPID.empty() || recipe.vecDeviceList.empty()) { |
| | | std::cerr << "[AddRecipe] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | if (!m_pDB || recipe.strPPID.empty() || recipe.vecDeviceList.empty()) { |
| | | std::cerr << "[AddRecipe] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string strTime = recipe.strCreateTime; |
| | | if (strTime.empty()) { |
| | | std::time_t now = std::time(nullptr); |
| | | std::tm tm_now = {}; |
| | | localtime_s(&tm_now, &now); |
| | | std::stringstream ss; |
| | | ss << std::put_time(&tm_now, "%Y-%m-%d %H:%M:%S"); |
| | | strTime = ss.str(); |
| | | } |
| | | std::string strTime = recipe.strCreateTime; |
| | | if (strTime.empty()) { |
| | | std::time_t now = std::time(nullptr); |
| | | std::tm tm_now = {}; |
| | | localtime_s(&tm_now, &now); |
| | | std::stringstream ss; |
| | | ss << std::put_time(&tm_now, "%Y-%m-%d %H:%M:%S"); |
| | | strTime = ss.str(); |
| | | } |
| | | |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | |
| | | // å¼å§äºå¡ |
| | | m_pDB->executeQuery("BEGIN TRANSACTION;"); |
| | | // å¼å§äºå¡ |
| | | m_pDB->executeQuery("BEGIN TRANSACTION;"); |
| | | |
| | | std::ostringstream oss; |
| | | oss << "INSERT OR REPLACE INTO recipes (ppid, description, create_time) VALUES ('" |
| | | << recipe.strPPID << "', '" |
| | | << recipe.strDescription << "', '" |
| | | << strTime << "');"; |
| | | std::ostringstream oss; |
| | | oss << "INSERT OR REPLACE INTO recipes (ppid, description, create_time) VALUES ('" |
| | | << recipe.strPPID << "', '" |
| | | << recipe.strDescription << "', '" |
| | | << strTime << "');"; |
| | | |
| | | if (!m_pDB->executeQuery(oss.str())) { |
| | | std::cerr << "[AddRecipe] Failed to insert recipe: " << recipe.strPPID << std::endl; |
| | | m_pDB->executeQuery("ROLLBACK;"); |
| | | return false; |
| | | } |
| | | if (!m_pDB->executeQuery(oss.str())) { |
| | | std::cerr << "[AddRecipe] Failed to insert recipe: " << recipe.strPPID << std::endl; |
| | | m_pDB->executeQuery("ROLLBACK;"); |
| | | return false; |
| | | } |
| | | |
| | | for (const auto& device : recipe.vecDeviceList) { |
| | | std::ostringstream devSql; |
| | | devSql << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id) VALUES ('" |
| | | << recipe.strPPID << "', " |
| | | << device.nDeviceID << ", '" |
| | | << device.strDeviceName << "', " |
| | | << device.nRecipeID << ");"; |
| | | for (const auto& device : recipe.vecDeviceList) { |
| | | std::ostringstream devSql; |
| | | devSql << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id, recipe_name) VALUES ('" |
| | | << recipe.strPPID << "', " |
| | | << device.nDeviceID << ", '" |
| | | << device.strDeviceName << "', " |
| | | << device.nRecipeID << ", '" |
| | | << device.strRecipeName << "');"; |
| | | |
| | | if (!m_pDB->executeQuery(devSql.str())) { |
| | | std::cerr << "[AddRecipe] Failed to insert device mapping: " << device.nDeviceID << std::endl; |
| | | m_pDB->executeQuery("ROLLBACK;"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // æäº¤äºå¡ |
| | | m_pDB->executeQuery("COMMIT;"); |
| | | return true; |
| | | if (!m_pDB->executeQuery(devSql.str())) { |
| | | std::cerr << "[AddRecipe] Failed to insert device mapping: " << device.nDeviceID << std::endl; |
| | | m_pDB->executeQuery("ROLLBACK;"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // æäº¤äºå¡ |
| | | m_pDB->executeQuery("COMMIT;"); |
| | | return true; |
| | | } |
| | | |
| | | bool RecipeManager::addRecipeDevice(const std::string& ppid, const DeviceRecipe& device) { |
| | | if (!m_pDB || ppid.empty() || device.nDeviceID <= 0 || device.nRecipeID <= 0) { |
| | | std::cerr << "[addRecipeDevice] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | if (!m_pDB || ppid.empty() || device.nDeviceID <= 0 || device.nRecipeID <= 0) { |
| | | std::cerr << "[addRecipeDevice] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | // æ£æ¥ ppid æ¯å¦åå¨ |
| | | // æ£æ¥ ppid æ¯å¦åå¨ |
| | | if (!ppidExists(ppid)) { |
| | | std::cerr << "[addRecipeDevice] PPID does not exist: " << ppid << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | // æå
¥è®¾å¤è®°å½ |
| | | std::ostringstream oss; |
| | | oss << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id) VALUES ('" |
| | | << ppid << "', " |
| | | << device.nDeviceID << ", '" |
| | | << device.strDeviceName << "', " |
| | | << device.nRecipeID << ");"; |
| | | // æå
¥è®¾å¤è®°å½ |
| | | std::ostringstream oss; |
| | | oss << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id, recipe_name) VALUES ('" |
| | | << ppid << "', " |
| | | << device.nDeviceID << ", '" |
| | | << device.strDeviceName << "', " |
| | | << device.nRecipeID << ", '" |
| | | << device.strRecipeName << "');"; |
| | | |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(oss.str()); |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(oss.str()); |
| | | } |
| | | |
| | | bool RecipeManager::deleteRecipeDeviceByID(const std::string& ppid, int nDeviceID) { |
| | | if (!m_pDB || ppid.empty() || nDeviceID <= 0) { |
| | | std::cerr << "[deleteRecipeDeviceByID] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | if (!m_pDB || ppid.empty() || nDeviceID <= 0) { |
| | | std::cerr << "[deleteRecipeDeviceByID] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::ostringstream oss; |
| | | oss << "DELETE FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_id = " << nDeviceID << ";"; |
| | | std::ostringstream oss; |
| | | oss << "DELETE FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_id = " << nDeviceID << ";"; |
| | | |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(oss.str()); |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(oss.str()); |
| | | } |
| | | |
| | | bool RecipeManager::deleteRecipeDeviceByName(const std::string& ppid, const std::string& strDeviceName) { |
| | | if (!m_pDB || ppid.empty() || strDeviceName.empty()) { |
| | | std::cerr << "[deleteRecipeDeviceByName] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | if (!m_pDB || ppid.empty() || strDeviceName.empty()) { |
| | | std::cerr << "[deleteRecipeDeviceByName] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::ostringstream oss; |
| | | oss << "DELETE FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_name = '" << strDeviceName << "';"; |
| | | std::ostringstream oss; |
| | | oss << "DELETE FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_name = '" << strDeviceName << "';"; |
| | | |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(oss.str()); |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(oss.str()); |
| | | } |
| | | |
| | | std::vector<RecipeInfo> RecipeManager::getAllRecipes() { |
| | | if (!m_pDB) { |
| | | return {}; |
| | | } |
| | | if (!m_pDB) { |
| | | return {}; |
| | | } |
| | | |
| | | std::vector<RecipeInfo> recipes; |
| | | auto rows = m_pDB->fetchResults("SELECT ppid, description, create_time FROM recipes;"); |
| | | std::vector<RecipeInfo> recipes; |
| | | auto rows = m_pDB->fetchResults("SELECT ppid, description, create_time FROM recipes;"); |
| | | |
| | | for (const auto& row : rows) { |
| | | RecipeInfo info; |
| | | info.strPPID = row[0]; |
| | | info.strDescription = row[1]; |
| | | info.strCreateTime = row[2]; |
| | | for (const auto& row : rows) { |
| | | RecipeInfo info; |
| | | info.strPPID = row[0]; |
| | | info.strDescription = row[1]; |
| | | info.strCreateTime = row[2]; |
| | | |
| | | std::ostringstream devQuery; |
| | | devQuery << "SELECT device_id, device_name, recipe_id FROM recipe_devices WHERE ppid = '" << info.strPPID << "';"; |
| | | auto devs = m_pDB->fetchResults(devQuery.str()); |
| | | std::ostringstream devQuery; |
| | | devQuery << "SELECT device_id, device_name, recipe_id, recipe_name FROM recipe_devices WHERE ppid = '" << info.strPPID << "'ORDER BY id ASC;"; |
| | | auto devs = m_pDB->fetchResults(devQuery.str()); |
| | | |
| | | for (const auto& dev : devs) { |
| | | DeviceRecipe dr; |
| | | try { |
| | | dr.nDeviceID = std::stoi(dev[0]); |
| | | dr.strDeviceName = dev[1]; |
| | | dr.nRecipeID = std::stoi(dev[2]); |
| | | } |
| | | catch (...) { |
| | | std::cerr << "Invalid data in recipe_devices for PPID: " << info.strPPID << std::endl; |
| | | continue; |
| | | } |
| | | info.vecDeviceList.push_back(dr); |
| | | } |
| | | recipes.push_back(info); |
| | | } |
| | | for (const auto& dev : devs) { |
| | | DeviceRecipe dr; |
| | | try { |
| | | dr.nDeviceID = std::stoi(dev[0]); |
| | | dr.strDeviceName = dev[1]; |
| | | dr.nRecipeID = std::stoi(dev[2]); |
| | | dr.strRecipeName = dev[3]; |
| | | } |
| | | catch (...) { |
| | | std::cerr << "Invalid data in recipe_devices for PPID: " << info.strPPID << std::endl; |
| | | continue; |
| | | } |
| | | info.vecDeviceList.push_back(dr); |
| | | } |
| | | recipes.push_back(info); |
| | | } |
| | | |
| | | return recipes; |
| | | return recipes; |
| | | } |
| | | |
| | | std::vector<RecipeInfo> RecipeManager::getRecipesByKeyword(const std::string& keyword) { |
| | | std::vector<RecipeInfo> recipes; |
| | | if (!m_pDB || keyword.empty()) { |
| | | return recipes; |
| | | } |
| | | std::vector<RecipeInfo> recipes; |
| | | if (!m_pDB || keyword.empty()) { |
| | | return recipes; |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT ppid, description, create_time FROM recipes " |
| | | << "WHERE ppid LIKE '%" << keyword << "%' OR description LIKE '%" << keyword << "%';"; |
| | | std::ostringstream query; |
| | | query << "SELECT ppid, description, create_time FROM recipes " |
| | | << "WHERE ppid LIKE '%" << keyword << "%' OR description LIKE '%" << keyword << "%';"; |
| | | |
| | | auto rows = m_pDB->fetchResults(query.str()); |
| | | for (const auto& row : rows) { |
| | | if (row.size() >= 3) { |
| | | RecipeInfo info; |
| | | info.strPPID = row[0]; |
| | | info.strDescription = row[1]; |
| | | info.strCreateTime = row[2]; |
| | | recipes.push_back(info); |
| | | } |
| | | } |
| | | return recipes; |
| | | auto rows = m_pDB->fetchResults(query.str()); |
| | | for (const auto& row : rows) { |
| | | if (row.size() >= 3) { |
| | | RecipeInfo info; |
| | | info.strPPID = row[0]; |
| | | info.strDescription = row[1]; |
| | | info.strCreateTime = row[2]; |
| | | recipes.push_back(info); |
| | | } |
| | | } |
| | | return recipes; |
| | | } |
| | | |
| | | std::vector<std::string> RecipeManager::getAllPPID() const { |
| | | std::vector<std::string> vecPPID; |
| | | std::vector<std::string> vecPPID; |
| | | |
| | | if (!m_pDB) { |
| | | return vecPPID; |
| | | } |
| | | if (!m_pDB) { |
| | | return vecPPID; |
| | | } |
| | | |
| | | const std::string query = "SELECT ppid FROM recipes ORDER BY ppid;"; |
| | | auto result = m_pDB->fetchResults(query); |
| | | const std::string query = "SELECT ppid FROM recipes ORDER BY ppid;"; |
| | | auto result = m_pDB->fetchResults(query); |
| | | |
| | | for (const auto& row : result) { |
| | | if (!row.empty()) { |
| | | vecPPID.push_back(row[0]); |
| | | } |
| | | } |
| | | for (const auto& row : result) { |
| | | if (!row.empty()) { |
| | | vecPPID.push_back(row[0]); |
| | | } |
| | | } |
| | | |
| | | return vecPPID; |
| | | return vecPPID; |
| | | } |
| | | |
| | | std::string RecipeManager::getPPIDById(int nId) { |
| | | if (!m_pDB) { |
| | | return {}; |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT ppid FROM recipes WHERE id = " << nId << ";"; |
| | | |
| | | auto rows = m_pDB->fetchResults(query.str()); |
| | | if (rows.empty() || rows[0].empty()) { |
| | | return {}; |
| | | } |
| | | |
| | | return rows[0][0]; |
| | | } |
| | | |
| | | int RecipeManager::getIdByPPID(const std::string& ppid) { |
| | | if (!m_pDB) { |
| | | return -1; |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT id FROM recipes WHERE ppid = '" << ppid << "';"; |
| | | |
| | | auto rows = m_pDB->fetchResults(query.str()); |
| | | if (rows.empty() || rows[0].empty()) { |
| | | return -1; |
| | | } |
| | | |
| | | try { |
| | | return std::stoi(rows[0][0]); |
| | | } |
| | | catch (...) { |
| | | std::cerr << "Invalid id value for PPID: " << ppid << std::endl; |
| | | return -1; |
| | | } |
| | | } |
| | | |
| | | RecipeInfo RecipeManager::getRecipeByPPID(const std::string& ppid) { |
| | | RecipeInfo info; |
| | | auto rows = m_pDB->fetchResults("SELECT ppid, description, create_time FROM recipes WHERE ppid = '" + ppid + "';"); |
| | | if (rows.empty()) { |
| | | return info; |
| | | } |
| | | RecipeInfo info; |
| | | auto rows = m_pDB->fetchResults("SELECT ppid, description, create_time FROM recipes WHERE ppid = '" + ppid + "';"); |
| | | if (rows.empty()) { |
| | | return info; |
| | | } |
| | | |
| | | info.strPPID = rows[0][0]; |
| | | info.strDescription = rows[0][1]; |
| | | info.strCreateTime = rows[0][2]; |
| | | info.strPPID = rows[0][0]; |
| | | info.strDescription = rows[0][1]; |
| | | info.strCreateTime = rows[0][2]; |
| | | |
| | | auto devs = m_pDB->fetchResults("SELECT device_id, device_name, recipe_id FROM recipe_devices WHERE ppid = '" + ppid + "';"); |
| | | for (const auto& dev : devs) { |
| | | DeviceRecipe dr; |
| | | try { |
| | | dr.nDeviceID = std::stoi(dev[0]); |
| | | dr.strDeviceName = dev[1]; |
| | | dr.nRecipeID = std::stoi(dev[2]); |
| | | } |
| | | catch (...) { |
| | | std::cerr << "Invalid data in recipe_devices for PPID: " << ppid << std::endl; |
| | | continue; |
| | | } |
| | | info.vecDeviceList.push_back(dr); |
| | | } |
| | | return info; |
| | | auto devs = m_pDB->fetchResults("SELECT device_id, device_name, recipe_id, recipe_name FROM recipe_devices WHERE ppid = '" + ppid + "';"); |
| | | for (const auto& dev : devs) { |
| | | DeviceRecipe dr; |
| | | try { |
| | | dr.nDeviceID = std::stoi(dev[0]); |
| | | dr.strDeviceName = dev[1]; |
| | | dr.nRecipeID = std::stoi(dev[2]); |
| | | dr.strRecipeName = dev[3]; |
| | | } |
| | | catch (...) { |
| | | std::cerr << "Invalid data in recipe_devices for PPID: " << ppid << std::endl; |
| | | continue; |
| | | } |
| | | info.vecDeviceList.push_back(dr); |
| | | } |
| | | return info; |
| | | } |
| | | |
| | | int RecipeManager::getDeviceRecipeIDByID(const std::string& ppid, int nDeviceID) { |
| | | if (!m_pDB || ppid.empty() || nDeviceID <= 0) { |
| | | return -1; |
| | | } |
| | | if (!m_pDB || ppid.empty() || nDeviceID <= 0) { |
| | | return -1; |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT recipe_id FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_id = " << nDeviceID << ";"; |
| | | std::ostringstream query; |
| | | query << "SELECT recipe_id FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_id = " << nDeviceID << ";"; |
| | | |
| | | auto result = m_pDB->fetchResults(query.str()); |
| | | if (!result.empty() && !result[0].empty()) { |
| | | try { |
| | | return std::stoi(result[0][0]); |
| | | } |
| | | catch (...) { |
| | | return -1; |
| | | } |
| | | } |
| | | return -1; |
| | | auto result = m_pDB->fetchResults(query.str()); |
| | | if (!result.empty() && !result[0].empty()) { |
| | | try { |
| | | return std::stoi(result[0][0]); |
| | | } |
| | | catch (...) { |
| | | return -1; |
| | | } |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | int RecipeManager::getDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName) { |
| | | if (!m_pDB || ppid.empty() || strDeviceName.empty()) { |
| | | return -1; |
| | | } |
| | | if (!m_pDB || ppid.empty() || strDeviceName.empty()) { |
| | | return -1; |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT recipe_id FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_name = '" << strDeviceName << "';"; |
| | | std::ostringstream query; |
| | | query << "SELECT recipe_id FROM recipe_devices WHERE ppid = '" << ppid << "' AND device_name = '" << strDeviceName << "';"; |
| | | |
| | | auto result = m_pDB->fetchResults(query.str()); |
| | | if (!result.empty() && !result[0].empty()) { |
| | | try { |
| | | return std::stoi(result[0][0]); |
| | | } |
| | | catch (...) { |
| | | return -1; |
| | | } |
| | | } |
| | | return -1; |
| | | auto result = m_pDB->fetchResults(query.str()); |
| | | if (!result.empty() && !result[0].empty()) { |
| | | try { |
| | | return std::stoi(result[0][0]); |
| | | } |
| | | catch (...) { |
| | | return -1; |
| | | } |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | bool RecipeManager::deleteRecipeByPPID(const std::string& ppid) { |
| | | if (!m_pDB) { |
| | | return false; |
| | | } |
| | | if (!m_pDB) { |
| | | return false; |
| | | } |
| | | |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery("DELETE FROM recipes WHERE ppid = '" + ppid + "';"); |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery("DELETE FROM recipes WHERE ppid = '" + ppid + "';"); |
| | | } |
| | | |
| | | bool RecipeManager::updateRecipe(const RecipeInfo& recipe) { |
| | | if (!m_pDB) { |
| | | return false; |
| | | } |
| | | if (!m_pDB) { |
| | | return false; |
| | | } |
| | | |
| | | if (recipe.strPPID.empty()) { |
| | | std::cerr << "Recipe PPID cannot be empty." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | deleteRecipeByPPID(recipe.strPPID); |
| | | return addRecipe(recipe); |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | deleteRecipeByPPID(recipe.strPPID); |
| | | return addRecipe(recipe); |
| | | } |
| | | |
| | | bool RecipeManager::updatePPID(const std::string& oldPPID, const std::string& newPPID) { |
| | | if (!m_pDB || oldPPID.empty() || newPPID.empty()) { |
| | | std::cerr << "[updatePPID] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | if (!m_pDB || oldPPID.empty() || newPPID.empty()) { |
| | | std::cerr << "[updatePPID] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | |
| | | // æ£æ¥æ¯å¦å·²ç»åå¨ç¸åç newPPID |
| | | auto check = m_pDB->fetchResults("SELECT COUNT(*) FROM recipes WHERE ppid = '" + newPPID + "';"); |
| | | if (!check.empty() && !check[0].empty() && check[0][0] != "0") { |
| | | std::cerr << "[updatePPID] New PPID already exists: " << newPPID << std::endl; |
| | | return false; |
| | | } |
| | | // æ£æ¥æ¯å¦å·²ç»åå¨ç¸åç newPPID |
| | | auto check = m_pDB->fetchResults("SELECT COUNT(*) FROM recipes WHERE ppid = '" + newPPID + "';"); |
| | | if (!check.empty() && !check[0].empty() && check[0][0] != "0") { |
| | | std::cerr << "[updatePPID] New PPID already exists: " << newPPID << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | m_pDB->executeQuery("BEGIN TRANSACTION;"); |
| | | m_pDB->executeQuery("BEGIN TRANSACTION;"); |
| | | |
| | | std::ostringstream sql; |
| | | sql << "UPDATE recipes SET ppid = '" << newPPID << "' WHERE ppid = '" << oldPPID << "';"; |
| | | if (!m_pDB->executeQuery(sql.str())) { |
| | | std::cerr << "[updatePPID] Failed to update recipes table." << std::endl; |
| | | m_pDB->executeQuery("ROLLBACK;"); |
| | | return false; |
| | | } |
| | | std::ostringstream sql; |
| | | sql << "UPDATE recipes SET ppid = '" << newPPID << "' WHERE ppid = '" << oldPPID << "';"; |
| | | if (!m_pDB->executeQuery(sql.str())) { |
| | | std::cerr << "[updatePPID] Failed to update recipes table." << std::endl; |
| | | m_pDB->executeQuery("ROLLBACK;"); |
| | | return false; |
| | | } |
| | | |
| | | m_pDB->executeQuery("COMMIT;"); |
| | | return true; |
| | | m_pDB->executeQuery("COMMIT;"); |
| | | return true; |
| | | } |
| | | |
| | | bool RecipeManager::updateDescription(const std::string& ppid, const std::string& newDescription) { |
| | | if (!m_pDB || ppid.empty()) { |
| | | std::cerr << "[updateRecipeDescription] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | if (!m_pDB || ppid.empty()) { |
| | | std::cerr << "[updateRecipeDescription] Invalid input." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::ostringstream oss; |
| | | oss << "UPDATE recipes SET description = '" << newDescription << "' WHERE ppid = '" << ppid << "';"; |
| | | std::ostringstream oss; |
| | | oss << "UPDATE recipes SET description = '" << newDescription << "' WHERE ppid = '" << ppid << "';"; |
| | | |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(oss.str()); |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(oss.str()); |
| | | } |
| | | |
| | | bool RecipeManager::updateDeviceRecipeIDByID(const std::string& ppid, int nDeviceID, int nNewRecipeID) { |
| | |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | query << "UPDATE recipe_devices SET recipe_id = " << nNewRecipeID |
| | | << " WHERE ppid = '" << ppid << "' AND device_id = " << nDeviceID << ";"; |
| | | return m_pDB->executeQuery(query.str()); |
| | |
| | | return false; |
| | | } |
| | | std::ostringstream query; |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | query << "UPDATE recipe_devices SET recipe_id = " << nNewRecipeID |
| | | << " WHERE ppid = '" << ppid << "' AND device_name = '" << strDeviceName << "';"; |
| | | return m_pDB->executeQuery(query.str()); |
| | | } |
| | | |
| | | bool RecipeManager::addDeviceRecipe(const std::string& strDeviceName, int nID, const std::string& strName, const std::string& strPara) { |
| | | if (!m_pDB || strDeviceName.empty() || nID <= 0 || strName.empty() || strPara.empty()) { |
| | | return false; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "CREATE TABLE IF NOT EXISTS " << strDeviceName << "_Recipes (" |
| | | << "recipe_id INTEGER PRIMARY KEY," |
| | | << "recipe_name TEXT NOT NULL," |
| | | << "recipe_para TEXT NOT NULL" |
| | | << ");"; |
| | | m_pDB->executeQuery(sql.str()); |
| | | |
| | | std::ostringstream ins; |
| | | ins << "INSERT OR REPLACE INTO " << strDeviceName |
| | | << "_Recipes (recipe_id, recipe_name, recipe_para) VALUES (" |
| | | << nID << ", '" << strName << "', '" << strPara << "');"; |
| | | |
| | | std::lock_guard<std::recursive_mutex> lk(m_mutex); |
| | | return m_pDB->executeQuery(ins.str()); |
| | | } |
| | | |
| | | bool RecipeManager::updateDeviceRecipeName(const std::string& strDeviceName, int nID, const std::string& strNewName) { |
| | | if (!m_pDB || strDeviceName.empty() || nID <= 0 || strNewName.empty()) { |
| | | return false; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "UPDATE " << strDeviceName << "_Recipes SET recipe_name='" << strNewName |
| | | << "' WHERE recipe_id=" << nID << ";"; |
| | | |
| | | std::lock_guard<std::recursive_mutex> lk(m_mutex); |
| | | return m_pDB->executeQuery(sql.str()); |
| | | } |
| | | |
| | | bool RecipeManager::updateDeviceRecipePara(const std::string& strDeviceName, int nID, const std::string& strNewPara) { |
| | | if (!m_pDB || strDeviceName.empty() || nID <= 0) { |
| | | return false; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "UPDATE " << strDeviceName << "_Recipes SET recipe_para='" << strNewPara |
| | | << "' WHERE recipe_id=" << nID << ";"; |
| | | |
| | | std::lock_guard<std::recursive_mutex> lk(m_mutex); |
| | | return m_pDB->executeQuery(sql.str()); |
| | | } |
| | | |
| | | std::string RecipeManager::getDeviceRecipeName(const std::string& strDeviceName, int nID) { |
| | | if (!m_pDB || strDeviceName.empty() || nID <= 0) { |
| | | return ""; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "SELECT recipe_name FROM " << strDeviceName << "_Recipes " |
| | | << "WHERE recipe_id=" << nID << " LIMIT 1;"; |
| | | |
| | | auto rows = m_pDB->fetchResults(sql.str()); |
| | | if (!rows.empty() && !rows[0].empty()) { |
| | | return rows[0][0]; |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | std::string RecipeManager::getDeviceRecipePara(const std::string& strDeviceName, int nID) { |
| | | if (!m_pDB || strDeviceName.empty() || nID <= 0) { |
| | | return ""; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "SELECT recipe_para FROM " << strDeviceName << "_Recipes " |
| | | << "WHERE recipe_id=" << nID << " LIMIT 1;"; |
| | | |
| | | auto rows = m_pDB->fetchResults(sql.str()); |
| | | if (!rows.empty() && !rows[0].empty()) { |
| | | return rows[0][0]; |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | bool RecipeManager::deleteDeviceRecipe(const std::string& strDeviceName, int nID) { |
| | | if (!m_pDB || strDeviceName.empty() || nID <= 0) { |
| | | return false; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "DELETE FROM " << strDeviceName << "_Recipes WHERE recipe_id=" << nID << ";"; |
| | | |
| | | std::lock_guard<std::recursive_mutex> lk(m_mutex); |
| | | return m_pDB->executeQuery(sql.str()); |
| | | } |
| | | |
| | | std::vector<std::pair<int, std::string>> RecipeManager::getDeviceRecipes(const std::string& strDeviceName) { |
| | | std::vector<std::pair<int, std::string>> out; |
| | | if (!m_pDB || strDeviceName.empty()) { |
| | | return out; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "SELECT recipe_id, recipe_name FROM " << strDeviceName << "_Recipes ORDER BY recipe_id;"; |
| | | |
| | | auto rows = m_pDB->fetchResults(sql.str()); |
| | | for (const auto& r : rows) { |
| | | if (r.size() < 2) continue; |
| | | try { |
| | | int id = std::stoi(r[0]); |
| | | out.emplace_back(id, r[1]); |
| | | } |
| | | catch (...) {} |
| | | } |
| | | return out; |
| | | } |
| | | |
| | | void RecipeManager::insertMockData() { |
| | | if (!m_pDB) { |
| | | return; |
| | | } |
| | | if (!m_pDB) { |
| | | return; |
| | | } |
| | | |
| | | RecipeInfo recipe; |
| | | recipe.strPPID = "P1001"; |
| | | recipe.strDescription = "Main Board Burn-in"; |
| | | RecipeInfo recipe; |
| | | recipe.strPPID = "P1001"; |
| | | recipe.strDescription = "Main Board Burn-in"; |
| | | |
| | | recipe.vecDeviceList = { |
| | | {1, 101, "Burner A"}, |
| | | {2, 102, "Burner B"} |
| | | }; |
| | | recipe.vecDeviceList = { |
| | | {9, 101, "VacuumBake", "VacuumBake"}, |
| | | {10, 102, "Bonder1", "Bonder1"}, |
| | | {11, 103, "Bonder2", "Bonder2"} |
| | | }; |
| | | |
| | | addRecipe(recipe); |
| | | addRecipe(recipe); |
| | | |
| | | addDeviceRecipe("Bonder1", 101, "æ åå·¥èº", ""); |
| | | addDeviceRecipe("Bonder1", 102, "æ¹è¯å·¥èº", ""); |
| | | addDeviceRecipe("Bonder1", 103, "é«é模å¼", ""); |
| | | |
| | | addDeviceRecipe("Bonder2", 101, "æ åå·¥èº", ""); |
| | | addDeviceRecipe("Bonder2", 102, "æ¹è¯å·¥èº", ""); |
| | | addDeviceRecipe("Bonder2", 103, "é«é模å¼", ""); |
| | | } |
| | | |
| | | bool RecipeManager::readRecipeFile(const std::string& filename) { |
| | | if (!m_pDB) { |
| | | return false; |
| | | } |
| | | if (!m_pDB) { |
| | | return false; |
| | | } |
| | | |
| | | std::ifstream file(filename); |
| | | if (!file.is_open()) { |
| | | return false; |
| | | } |
| | | std::ifstream file(filename); |
| | | if (!file.is_open()) { |
| | | return false; |
| | | } |
| | | |
| | | std::unordered_map<std::string, RecipeInfo> recipeMap; |
| | | std::string line; |
| | | std::getline(file, line); // skip header |
| | | std::unordered_map<std::string, RecipeInfo> recipeMap; |
| | | std::string line; |
| | | std::getline(file, line); // skip header |
| | | |
| | | while (std::getline(file, line)) { |
| | | std::stringstream ss(line); |
| | | std::string cell; |
| | | std::string ppid, description, createTime; |
| | | DeviceRecipe dev; |
| | | while (std::getline(file, line)) { |
| | | std::stringstream ss(line); |
| | | std::string cell; |
| | | std::string ppid, description, createTime; |
| | | DeviceRecipe dev; |
| | | |
| | | std::getline(ss, ppid, ','); |
| | | std::getline(ss, cell, ','); |
| | | try { dev.nDeviceID = std::stoi(cell); } |
| | | catch (...) { continue; } |
| | | std::getline(ss, dev.strDeviceName, ','); |
| | | std::getline(ss, cell, ','); |
| | | try { dev.nRecipeID = std::stoi(cell); } |
| | | catch (...) { continue; } |
| | | std::getline(ss, description, ','); |
| | | std::getline(ss, createTime, ','); |
| | | std::getline(ss, ppid, ','); |
| | | std::getline(ss, cell, ','); |
| | | try { dev.nDeviceID = std::stoi(cell); } |
| | | catch (...) { continue; } |
| | | std::getline(ss, dev.strDeviceName, ','); |
| | | std::getline(ss, cell, ','); |
| | | try { dev.nRecipeID = std::stoi(cell); } |
| | | catch (...) { continue; } |
| | | std::getline(ss, dev.strRecipeName, ','); |
| | | std::getline(ss, description, ','); |
| | | std::getline(ss, createTime, ','); |
| | | |
| | | auto& recipe = recipeMap[ppid]; |
| | | recipe.strPPID = ppid; |
| | | recipe.strDescription = description; |
| | | recipe.strCreateTime = createTime; |
| | | recipe.vecDeviceList.push_back(dev); |
| | | } |
| | | auto& recipe = recipeMap[ppid]; |
| | | recipe.strPPID = ppid; |
| | | recipe.strDescription = description; |
| | | recipe.strCreateTime = createTime; |
| | | recipe.vecDeviceList.push_back(dev); |
| | | } |
| | | |
| | | for (const auto& pair : recipeMap) { |
| | | if (!updateRecipe(pair.second)) { |
| | | std::cerr << "Failed to update recipe from file: " << pair.first << std::endl; |
| | | } |
| | | } |
| | | for (const auto& pair : recipeMap) { |
| | | if (!updateRecipe(pair.second)) { |
| | | std::cerr << "Failed to update recipe from file: " << pair.first << std::endl; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | return true; |
| | | } |
| | | |
| | | bool RecipeManager::saveRecipeFile(const std::string& filename) { |
| | | if (!m_pDB) { |
| | | return false; |
| | | } |
| | | if (!m_pDB) { |
| | | return false; |
| | | } |
| | | |
| | | std::ofstream file(filename); |
| | | if (!file.is_open()) { |
| | | return false; |
| | | } |
| | | std::ofstream file(filename); |
| | | if (!file.is_open()) { |
| | | return false; |
| | | } |
| | | |
| | | file << "PPID,DeviceID,DeviceName,RecipeID,Description,CreateTime\n"; |
| | | auto recipes = getAllRecipes(); |
| | | for (const auto& recipe : recipes) { |
| | | for (const auto& dev : recipe.vecDeviceList) { |
| | | file << recipe.strPPID << "," |
| | | << dev.nDeviceID << "," |
| | | << dev.strDeviceName << "," |
| | | << dev.nRecipeID << "," |
| | | << recipe.strDescription << "," |
| | | << recipe.strCreateTime << "\n"; |
| | | } |
| | | } |
| | | file << "PPID,DeviceID,DeviceName,RecipeID,RecipeName,Description,CreateTime\n"; |
| | | auto recipes = getAllRecipes(); |
| | | for (const auto& recipe : recipes) { |
| | | for (const auto& dev : recipe.vecDeviceList) { |
| | | file << recipe.strPPID << "," |
| | | << dev.nDeviceID << "," |
| | | << dev.strDeviceName << "," |
| | | << dev.nRecipeID << "," |
| | | << dev.strRecipeName << "," |
| | | << recipe.strDescription << "," |
| | | << recipe.strCreateTime << "\n"; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | return true; |
| | | } |
| | |
| | | #ifndef RECIPE_MANAGER_H |
| | | #ifndef RECIPE_MANAGER_H |
| | | #define RECIPE_MANAGER_H |
| | | |
| | | #include <string> |
| | |
| | | #include <mutex> |
| | | #include <unordered_map> |
| | | #include "Database.h" |
| | | #include "CParam.h" |
| | | |
| | | // å个设å¤é
æ¹æ å°ä¿¡æ¯ |
| | | |
| | | // å个设å¤é
æ¹æ å°ä¿¡æ¯ |
| | | struct DeviceRecipe { |
| | | int nDeviceID; // 设å¤ID |
| | | int nRecipeID; // åé
æ¹ID |
| | | std::string strRecipeName; // åé
æ¹åç§° |
| | | std::string strDeviceName; // 设å¤åç§° |
| | | int nDeviceID; // 设å¤ID |
| | | int nRecipeID; // åé
æ¹ID |
| | | std::string strRecipeName; // 设å¤åç§° |
| | | std::string strDeviceName; // åé
æ¹åç§° |
| | | std::vector<uint8_t> paramsRawData; // åå§åæ°æ°æ® |
| | | std::vector<CParam*> m_params; // åæ°å¯¹è±¡å表 |
| | | }; |
| | | |
| | | // é
æ¹ä¿¡æ¯ |
| | | // é
æ¹ä¿¡æ¯ |
| | | struct RecipeInfo { |
| | | std::string strPPID; // é
æ¹ID |
| | | std::string strDescription; // é
æ¹æè¿° |
| | | std::string strCreateTime; // å建æ¶é´ |
| | | std::vector<DeviceRecipe> vecDeviceList; // å
³èç设å¤ä¿¡æ¯å表 |
| | | std::string strPPID; // é
æ¹ID |
| | | std::string strDescription; // é
æ¹æè¿° |
| | | std::string strCreateTime; // å建æ¶é´ |
| | | std::vector<DeviceRecipe> vecDeviceList; // å
³èç设å¤ä¿¡æ¯å表 |
| | | }; |
| | | |
| | | using RecipeMap = std::unordered_map<std::string, RecipeInfo>; // æ PPID æ å°çé
æ¹è¡¨ |
| | | using RecipeMap = std::unordered_map<std::string, RecipeInfo>; // æ PPID æ å°çé
æ¹è¡¨ |
| | | |
| | | class RecipeManager { |
| | | public: |
| | | // è·ååä¾ |
| | | static RecipeManager& getInstance(); |
| | | // è·ååä¾ |
| | | static RecipeManager& getInstance(); |
| | | |
| | | // åå§åé
æ¹æ°æ®åº |
| | | bool initRecipeTable(); |
| | | // åå§åé
æ¹æ°æ®åº |
| | | bool initRecipeTable(); |
| | | |
| | | // éæ¯è¡¨æå
³éè¿æ¥ |
| | | void termRecipeTable(); |
| | | bool destroyRecipeTable(); |
| | | // éæ¯è¡¨æå
³éè¿æ¥ |
| | | void termRecipeTable(); |
| | | bool destroyRecipeTable(); |
| | | |
| | | // æ£æ¥ PPID æ¯å¦åå¨ |
| | | bool ppidExists(const std::string& ppid); |
| | | // æ£æ¥ PPID æ¯å¦åå¨ |
| | | bool ppidExists(const std::string& ppid); |
| | | |
| | | // æ£æ¥è®¾å¤æ¯å¦åå¨äºæå® PPID çé
æ¹ä¸ |
| | | // æ£æ¥è®¾å¤æ¯å¦åå¨äºæå® PPID çé
æ¹ä¸ |
| | | bool deviceExists(const std::string& ppid, int nDeviceID); |
| | | |
| | | // æ·»å ä¸ä¸ªé
æ¹åå
¶è®¾å¤æ å° |
| | | bool addRecipe(const RecipeInfo& recipe); |
| | | // æ·»å ä¸ä¸ªé
æ¹åå
¶è®¾å¤æ å° |
| | | bool addRecipe(const RecipeInfo& recipe); |
| | | |
| | | // æ·»å 设å¤å°æå®é
æ¹ |
| | | bool addRecipeDevice(const std::string& ppid, const DeviceRecipe& device); |
| | | // æ·»å 设å¤å°æå®é
æ¹ |
| | | bool addRecipeDevice(const std::string& ppid, const DeviceRecipe& device); |
| | | |
| | | // å é¤æå® PPID ç设å¤é
æ¹ |
| | | bool deleteRecipeDeviceByID(const std::string& ppid, int nDeviceID); |
| | | // å é¤æå® PPID ç设å¤é
æ¹ |
| | | bool deleteRecipeDeviceByID(const std::string& ppid, int nDeviceID); |
| | | |
| | | // å é¤æå® PPID ç设å¤é
æ¹ï¼éè¿è®¾å¤åç§°ï¼ |
| | | bool deleteRecipeDeviceByName(const std::string& ppid, const std::string& strDeviceName); |
| | | // å é¤æå® PPID ç设å¤é
æ¹ï¼éè¿è®¾å¤åç§°ï¼ |
| | | bool deleteRecipeDeviceByName(const std::string& ppid, const std::string& strDeviceName); |
| | | |
| | | // æ¥è¯¢ææé
æ¹ |
| | | std::vector<RecipeInfo> getAllRecipes(); |
| | | // æ¥è¯¢ææé
æ¹ |
| | | std::vector<RecipeInfo> getAllRecipes(); |
| | | |
| | | // æ ¹æ® PPID ææè¿°æ¥è¯¢é
æ¹ |
| | | std::vector<RecipeInfo> getRecipesByKeyword(const std::string& keyword); |
| | | // æ ¹æ® PPID ææè¿°æ¥è¯¢é
æ¹ |
| | | std::vector<RecipeInfo> getRecipesByKeyword(const std::string& keyword); |
| | | |
| | | // è·åææ PPID |
| | | std::vector<std::string> getAllPPID() const; |
| | | // è·åææ PPID |
| | | std::vector<std::string> getAllPPID() const; |
| | | |
| | | // æ PPID æ¥è¯¢é
æ¹ |
| | | RecipeInfo getRecipeByPPID(const std::string& ppid); |
| | | // æ ID æ¥è¯¢ PPID |
| | | std::string getPPIDById(int nId); |
| | | |
| | | // æ ¹æ® PPID å设å¤ID è·å设å¤é
æ¹ID |
| | | int getDeviceRecipeIDByID(const std::string& ppid, int nDeviceID); |
| | | // æ PPID æ¥è¯¢ ID |
| | | int getIdByPPID(const std::string& ppid); |
| | | |
| | | // æ ¹æ® PPID å设å¤åç§° è·å设å¤é
æ¹ID |
| | | int getDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName); |
| | | // æ PPID æ¥è¯¢é
æ¹ |
| | | RecipeInfo getRecipeByPPID(const std::string& ppid); |
| | | |
| | | // å é¤æå® PPID çé
æ¹ |
| | | bool deleteRecipeByPPID(const std::string& ppid); |
| | | // æ ¹æ® PPID å设å¤ID è·å设å¤é
æ¹ID |
| | | int getDeviceRecipeIDByID(const std::string& ppid, int nDeviceID); |
| | | |
| | | // æ´æ°æå® PPID çé
æ¹ |
| | | bool updateRecipe(const RecipeInfo& recipe); |
| | | // æ ¹æ® PPID å设å¤åç§° è·å设å¤é
æ¹ID |
| | | int getDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName); |
| | | |
| | | // æ´æ° PPIDï¼éè¿æ§ PPID åæ° PPIDï¼ |
| | | bool updatePPID(const std::string& oldPPID, const std::string& newPPID); |
| | | // å é¤æå® PPID çé
æ¹ |
| | | bool deleteRecipeByPPID(const std::string& ppid); |
| | | |
| | | // æ´æ°é
æ¹æè¿°ï¼éè¿ PPIDï¼ |
| | | bool updateDescription(const std::string& ppid, const std::string& newDescription); |
| | | // æ´æ°æå® PPID çé
æ¹ |
| | | bool updateRecipe(const RecipeInfo& recipe); |
| | | |
| | | // æ´æ°è®¾å¤é
æ¹IDï¼éè¿ PPID å设å¤IDï¼ |
| | | bool updateDeviceRecipeIDByID(const std::string& ppid, int nDeviceID, int nNewRecipeID); |
| | | // æ´æ° PPIDï¼éè¿æ§ PPID åæ° PPIDï¼ |
| | | bool updatePPID(const std::string& oldPPID, const std::string& newPPID); |
| | | |
| | | // æ´æ°è®¾å¤é
æ¹IDï¼éè¿ PPID å设å¤åç§°ï¼ |
| | | bool updateDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName, int nNewRecipeID); |
| | | // æ´æ°é
æ¹æè¿°ï¼éè¿ PPIDï¼ |
| | | bool updateDescription(const std::string& ppid, const std::string& newDescription); |
| | | |
| | | // 模ææå
¥æ°æ®ï¼æµè¯ç¨ï¼ |
| | | void insertMockData(); |
| | | // æ´æ°è®¾å¤é
æ¹IDï¼éè¿ PPID å设å¤IDï¼ |
| | | bool updateDeviceRecipeIDByID(const std::string& ppid, int nDeviceID, int nNewRecipeID); |
| | | |
| | | // 读åé
æ¹æä»¶ï¼CSV æ JSONï¼ |
| | | bool readRecipeFile(const std::string& filename); |
| | | // æ´æ°è®¾å¤é
æ¹IDï¼éè¿ PPID å设å¤åç§°ï¼ |
| | | bool updateDeviceRecipeIDByName(const std::string& ppid, const std::string& strDeviceName, int nNewRecipeID); |
| | | |
| | | // ä¿åé
æ¹å°æä»¶ |
| | | bool saveRecipeFile(const std::string& filename); |
| | | bool addDeviceRecipe(const std::string& strDeviceName, int nID, const std::string& strName, const std::string& strPara); |
| | | bool updateDeviceRecipeName(const std::string& strDeviceName, int nID, const std::string& strNewName); |
| | | bool updateDeviceRecipePara(const std::string& strDeviceName, int nID, const std::string& strNewPara); |
| | | std::string getDeviceRecipeName(const std::string& strDeviceName, int nID); |
| | | std::string getDeviceRecipePara(const std::string& strDeviceName, int nID); |
| | | bool deleteDeviceRecipe(const std::string& strDeviceName, int nID); |
| | | std::vector<std::pair<int, std::string>> getDeviceRecipes(const std::string& strDeviceName); |
| | | |
| | | // 模ææå
¥æ°æ®ï¼æµè¯ç¨ï¼ |
| | | void insertMockData(); |
| | | |
| | | // 读åé
æ¹æä»¶ï¼CSV æ JSONï¼ |
| | | bool readRecipeFile(const std::string& filename); |
| | | |
| | | // ä¿åé
æ¹å°æä»¶ |
| | | bool saveRecipeFile(const std::string& filename); |
| | | |
| | | private: |
| | | RecipeManager(); |
| | | ~RecipeManager(); |
| | | RecipeManager(); |
| | | ~RecipeManager(); |
| | | |
| | | RecipeManager(const RecipeManager&) = delete; |
| | | RecipeManager& operator=(const RecipeManager&) = delete; |
| | | RecipeManager(const RecipeManager&) = delete; |
| | | RecipeManager& operator=(const RecipeManager&) = delete; |
| | | |
| | | private: |
| | | BL::Database* m_pDB; |
| | | static std::recursive_mutex m_mutex; |
| | | BL::Database* m_pDB; |
| | | static std::recursive_mutex m_mutex; |
| | | }; |
| | | |
| | | #endif // RECIPE_MANAGER_H |
| | |
| | | <ClInclude Include="CPageLinkSignal.h" /> |
| | | <ClInclude Include="CPageReport.h" /> |
| | | <ClInclude Include="CPageVarialbles.h" /> |
| | | <ClInclude Include="CParam.h" /> |
| | | <ClInclude Include="CReport.h" /> |
| | | <ClInclude Include="CRobotCmdContainerDlg.h" /> |
| | | <ClInclude Include="CRobotCmdTestDlg.h" /> |
| | |
| | | <ClCompile Include="CPageLinkSignal.cpp" /> |
| | | <ClCompile Include="CPageReport.cpp" /> |
| | | <ClCompile Include="CPageVarialbles.cpp" /> |
| | | <ClCompile Include="CParam.cpp" /> |
| | | <ClCompile Include="CReport.cpp" /> |
| | | <ClCompile Include="CRobotCmdContainerDlg.cpp" /> |
| | | <ClCompile Include="CRobotCmdTestDlg.cpp" /> |
| | |
| | | <ClCompile Include="CControlJob.cpp" /> |
| | | <ClCompile Include="CExpandableListCtrl.cpp" /> |
| | | <ClCompile Include="CControlJobDlg.cpp" /> |
| | | <ClCompile Include="CParam.cpp" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="AlarmManager.h" /> |
| | |
| | | <ClInclude Include="SerializeUtil.h" /> |
| | | <ClInclude Include="CExpandableListCtrl.h" /> |
| | | <ClInclude Include="CControlJobDlg.h" /> |
| | | <ClInclude Include="CParam.h" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ResourceCompile Include="Servo.rc" /> |
| | |
| | | #include "CPageReport.h" |
| | | #include "CPageCollectionEvent.h" |
| | | #include "CControlJobDlg.h" |
| | | #include "InputDialog.h" |
| | | |
| | | |
| | | #ifdef _DEBUG |
| | |
| | | LRESULT CServoDlg::OnToolbarBtnClicked(WPARAM wParam, LPARAM lParam) |
| | | { |
| | | int id = (int)lParam; |
| | | if (id == IDC_BUTTON_RUN || id == IDC_BUTTON_STOP) { |
| | | //CInputDialog inputDialog(_T("éªè¯ç¨æ·"), _T("请è¾å
¥ç¨æ·å¯ç ï¼")); |
| | | //if (inputDialog.DoModal() != IDOK) { |
| | | // AfxMessageBox(_T("åæ¶éªè¯ï¼")); |
| | | // return 0; |
| | | //} |
| | | |
| | | //CString inputText = inputDialog.GetInputText(); |
| | | //std::string strPass = UserManager::getInstance().getCurrentPass(); |
| | | //if (inputText.Compare(strPass.c_str()) != 0) { |
| | | // AfxMessageBox(_T("å¯ç é误ï¼")); |
| | | // SystemLogManager::getInstance().log(SystemLogManager::LogType::Info, _T("éªè¯æ¶ï¼å¯ç é误ï¼")); |
| | | // return 0; |
| | | //} |
| | | |
| | | UserRole emRole = UserManager::getInstance().getCurrentUserRole(); |
| | | if (emRole != UserRole::SuperAdmin) { |
| | | AfxMessageBox(_T("å½åç¨æ·å¹¶é管çåï¼ï¼ï¼")); |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | if (id == IDC_BUTTON_RUN) { |
| | | if (theApp.m_model.getMaster().getState() == SERVO::MASTERSTATE::MSERROR) { |
| | | AfxMessageBox("å½åææºå°åçé误ï¼ä¸è½å¯å¨ï¼è¯·ç¡®è®¤è§£å³é®é¢ååå°è¯éæ°å¯å¨ï¼"); |
| | |
| | | #include "stdafx.h" |
| | | #include "stdafx.h" |
| | | #include "UserManager.h" |
| | | #include <chrono> |
| | | #include <iostream> |
| | |
| | | const std::string INITIAL_ADMIN_USERNAME = "admin"; |
| | | const std::string INITIAL_ADMIN_PASSWORD = "admin"; |
| | | |
| | | // è·ååä¾å®ä¾ |
| | | // è·ååä¾å®ä¾ |
| | | UserManager& UserManager::getInstance() { |
| | | static UserManager instance; |
| | | return instance; |
| | | static UserManager instance; |
| | | return instance; |
| | | } |
| | | |
| | | UserManager::UserManager() |
| | | : m_isLoggedIn(false), m_isRememberMe(false), m_tmSessionTimeout(std::chrono::minutes(30)), |
| | | m_tmSessionExpiration(std::chrono::hours(72)), m_hMouseHook(nullptr), m_hKeyboardHook(nullptr), |
| | | m_pDB(std::make_unique<BL::SQLiteDatabase>()) { |
| | | initializeDatabase(); |
| | | : m_isLoggedIn(false), m_isRememberMe(false), m_tmSessionTimeout(std::chrono::minutes(30)), |
| | | m_tmSessionExpiration(std::chrono::hours(72)), m_hMouseHook(nullptr), m_hKeyboardHook(nullptr), |
| | | m_pDB(std::make_unique<BL::SQLiteDatabase>()) { |
| | | initializeDatabase(); |
| | | } |
| | | |
| | | UserManager::~UserManager() { |
| | | terminateIdleDetection(); |
| | | terminateIdleDetection(); |
| | | } |
| | | |
| | | // æä¾æ°æ®åºè¿æ¥ |
| | | // æä¾æ°æ®åºè¿æ¥ |
| | | std::unique_ptr<BL::Database>& UserManager::getDatabaseInstance() { |
| | | return m_pDB; |
| | | return m_pDB; |
| | | } |
| | | |
| | | // åå§åæ°æ®åºï¼åå»ºç¨æ·è¡¨å¹¶æå
¥åå§ç®¡çåç¨æ· |
| | | // åå§åæ°æ®åºï¼åå»ºç¨æ·è¡¨å¹¶æå
¥åå§ç®¡çåç¨æ· |
| | | bool UserManager::initializeDatabase() { |
| | | std::string dbFilePath = getDatabaseFilePath(); |
| | | if (!m_pDB->connect(dbFilePath, true)) { |
| | | throw std::runtime_error("Failed to connect to database."); |
| | | } |
| | | std::string dbFilePath = getDatabaseFilePath(); |
| | | if (!m_pDB->connect(dbFilePath, true)) { |
| | | throw std::runtime_error("Failed to connect to database."); |
| | | } |
| | | |
| | | std::string createTableQuery = R"( |
| | | CREATE TABLE IF NOT EXISTS users ( |
| | | username VARCHAR(50) PRIMARY KEY, |
| | | password VARCHAR(255) NOT NULL, |
| | | role INT NOT NULL, |
| | | session_timeout INT DEFAULT 30, |
| | | session_expiration INT DEFAULT 72, |
| | | last_login DATETIME DEFAULT (datetime('now', 'localtime')) |
| | | ) |
| | | )"; |
| | | m_pDB->executeQuery(createTableQuery); |
| | | std::string createTableQuery = R"( |
| | | CREATE TABLE IF NOT EXISTS users ( |
| | | username VARCHAR(50) PRIMARY KEY, |
| | | password VARCHAR(255) NOT NULL, |
| | | role INT NOT NULL, |
| | | session_timeout INT DEFAULT 30, |
| | | session_expiration INT DEFAULT 72, |
| | | last_login DATETIME DEFAULT (datetime('now', 'localtime')) |
| | | ) |
| | | )"; |
| | | m_pDB->executeQuery(createTableQuery); |
| | | |
| | | std::string checkAdminQuery = "SELECT COUNT(*) FROM users WHERE role = 0"; |
| | | auto result = m_pDB->fetchResults(checkAdminQuery); |
| | | std::string checkAdminQuery = "SELECT COUNT(*) FROM users WHERE role = 0"; |
| | | auto result = m_pDB->fetchResults(checkAdminQuery); |
| | | |
| | | if (result.empty() || result[0][0] == "0") { |
| | | std::string insertAdminQuery = "INSERT INTO users (username, password, role, session_timeout, session_expiration) VALUES ('" + |
| | | INITIAL_ADMIN_USERNAME + "', '" + simpleEncryptDecrypt(INITIAL_ADMIN_PASSWORD, "BandKey") + "', 0, 30, 72)"; |
| | | m_pDB->executeQuery(insertAdminQuery); |
| | | } |
| | | if (result.empty() || result[0][0] == "0") { |
| | | std::string insertAdminQuery = "INSERT INTO users (username, password, role, session_timeout, session_expiration) VALUES ('" + |
| | | INITIAL_ADMIN_USERNAME + "', '" + simpleEncryptDecrypt(INITIAL_ADMIN_PASSWORD, "BandKey") + "', 0, 30, 72)"; |
| | | m_pDB->executeQuery(insertAdminQuery); |
| | | } |
| | | |
| | | return true; |
| | | return true; |
| | | } |
| | | |
| | | // 对å¯ç è¿è¡åå¸å¤ç |
| | | // 对å¯ç è¿è¡åå¸å¤ç |
| | | std::string UserManager::hashPassword(const std::string& password) { |
| | | return std::to_string(std::hash<std::string>{}(password)); |
| | | return std::to_string(std::hash<std::string>{}(password)); |
| | | } |
| | | |
| | | // ç®åçå å¯åè§£å¯å½æ° |
| | | // ç®åçå å¯åè§£å¯å½æ° |
| | | std::string UserManager::simpleEncryptDecrypt(const std::string& data, const std::string& key) { |
| | | std::string result = data; |
| | | for (size_t i = 0; i < data.size(); ++i) { |
| | | result[i] ^= key[i % key.size()]; // ç®å弿å å¯ |
| | | } |
| | | return result; |
| | | std::string result = data; |
| | | for (size_t i = 0; i < data.size(); ++i) { |
| | | result[i] ^= key[i % key.size()]; // ç®å弿å å¯ |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | // ä»ä¼è¯æä»¶å è½½ä¼è¯ä¿¡æ¯ |
| | | // ä»ä¼è¯æä»¶å è½½ä¼è¯ä¿¡æ¯ |
| | | bool UserManager::loadSession() { |
| | | std::ifstream sessionFile(getSessionFilePath(), std::ios::binary); |
| | | if (!sessionFile.is_open()) { |
| | | return false; |
| | | } |
| | | std::ifstream sessionFile(getSessionFilePath(), std::ios::binary); |
| | | if (!sessionFile.is_open()) { |
| | | return false; |
| | | } |
| | | |
| | | // ä»æä»¶è¯»åå 坿°æ® |
| | | std::string encryptedData((std::istreambuf_iterator<char>(sessionFile)), std::istreambuf_iterator<char>()); |
| | | sessionFile.close(); |
| | | // ä»æä»¶è¯»åå 坿°æ® |
| | | std::string encryptedData((std::istreambuf_iterator<char>(sessionFile)), std::istreambuf_iterator<char>()); |
| | | sessionFile.close(); |
| | | |
| | | // è§£å¯æ°æ® |
| | | std::string decryptedData = simpleEncryptDecrypt(encryptedData, "my_secret_key"); |
| | | // è§£å¯æ°æ® |
| | | std::string decryptedData = simpleEncryptDecrypt(encryptedData, "my_secret_key"); |
| | | |
| | | // è§£æè§£å¯çæ°æ® |
| | | std::istringstream sessionData(decryptedData); |
| | | std::string username; |
| | | // è§£æè§£å¯çæ°æ® |
| | | std::istringstream sessionData(decryptedData); |
| | | std::string username; |
| | | std::string password; |
| | | std::time_t lastLoginTime; |
| | | int timeoutMinutes; |
| | | int expirationHours; |
| | | std::time_t lastLoginTime; |
| | | int timeoutMinutes; |
| | | int expirationHours; |
| | | |
| | | sessionData >> username >> password >> lastLoginTime >> timeoutMinutes >> expirationHours; |
| | | sessionData >> username >> password >> lastLoginTime >> timeoutMinutes >> expirationHours; |
| | | |
| | | // éªè¯æ¶é´æ³æææ§ |
| | | auto now = std::chrono::system_clock::now(); |
| | | auto lastLogin = std::chrono::system_clock::from_time_t(lastLoginTime); |
| | | auto sessionDuration = std::chrono::duration_cast<std::chrono::hours>(now - lastLogin); |
| | | // éªè¯æ¶é´æ³æææ§ |
| | | auto now = std::chrono::system_clock::now(); |
| | | auto lastLogin = std::chrono::system_clock::from_time_t(lastLoginTime); |
| | | auto sessionDuration = std::chrono::duration_cast<std::chrono::hours>(now - lastLogin); |
| | | |
| | | if (sessionDuration > std::chrono::hours(expirationHours)) { |
| | | clearSession(); |
| | | return false; |
| | | } |
| | | if (sessionDuration > std::chrono::hours(expirationHours)) { |
| | | clearSession(); |
| | | return false; |
| | | } |
| | | |
| | | // æ¢å¤ä¼è¯æ°æ® |
| | | m_strCurrentUser = username; |
| | | // æ¢å¤ä¼è¯æ°æ® |
| | | m_strCurrentUser = username; |
| | | m_strCurrentPass = password; |
| | | m_tpLastLogin = lastLogin; |
| | | m_tmSessionTimeout = std::chrono::minutes(timeoutMinutes); |
| | | m_tmSessionExpiration = std::chrono::hours(expirationHours); |
| | | m_isLoggedIn = true; |
| | | m_isRememberMe = true; |
| | | updateActivityTime(); |
| | | m_tpLastLogin = lastLogin; |
| | | m_tmSessionTimeout = std::chrono::minutes(timeoutMinutes); |
| | | m_tmSessionExpiration = std::chrono::hours(expirationHours); |
| | | m_isLoggedIn = true; |
| | | m_isRememberMe = true; |
| | | updateActivityTime(); |
| | | |
| | | return true; |
| | | return true; |
| | | } |
| | | |
| | | // ä¿åä¼è¯ä¿¡æ¯å°æä»¶ |
| | | // ä¿åä¼è¯ä¿¡æ¯å°æä»¶ |
| | | void UserManager::saveSession() { |
| | | if (!m_isRememberMe) { |
| | | clearSession(); |
| | | return; |
| | | } |
| | | if (!m_isRememberMe) { |
| | | clearSession(); |
| | | return; |
| | | } |
| | | |
| | | // åå§ä¼è¯æ°æ® |
| | | std::stringstream sessionData; |
| | | std::time_t lastLoginTime = std::chrono::system_clock::to_time_t(m_tpLastLogin); |
| | | sessionData << m_strCurrentUser << " " << m_strCurrentPass << " " << lastLoginTime << " " |
| | | << m_tmSessionTimeout.count() << " " << m_tmSessionExpiration.count(); |
| | | // åå§ä¼è¯æ°æ® |
| | | std::stringstream sessionData; |
| | | std::time_t lastLoginTime = std::chrono::system_clock::to_time_t(m_tpLastLogin); |
| | | sessionData << m_strCurrentUser << " " << m_strCurrentPass << " " << lastLoginTime << " " |
| | | << m_tmSessionTimeout.count() << " " << m_tmSessionExpiration.count(); |
| | | |
| | | // å 坿°æ® |
| | | std::string encryptedData = simpleEncryptDecrypt(sessionData.str(), "my_secret_key"); |
| | | // å 坿°æ® |
| | | std::string encryptedData = simpleEncryptDecrypt(sessionData.str(), "my_secret_key"); |
| | | |
| | | // åå
¥å 坿°æ®å°æä»¶ |
| | | std::ofstream sessionFile(getSessionFilePath(), std::ios::binary); |
| | | if (sessionFile.is_open()) { |
| | | sessionFile << encryptedData; |
| | | sessionFile.close(); |
| | | } |
| | | // åå
¥å 坿°æ®å°æä»¶ |
| | | std::ofstream sessionFile(getSessionFilePath(), std::ios::binary); |
| | | if (sessionFile.is_open()) { |
| | | sessionFile << encryptedData; |
| | | sessionFile.close(); |
| | | } |
| | | } |
| | | |
| | | // æ¸
é¤ä¼è¯æä»¶ |
| | | // æ¸
é¤ä¼è¯æä»¶ |
| | | void UserManager::clearSession() { |
| | | std::remove(getSessionFilePath().c_str()); |
| | | std::remove(getSessionFilePath().c_str()); |
| | | } |
| | | |
| | | // è·åç¨åºè·¯å¾ä¸çconfigæä»¶å¤¹è·¯å¾ |
| | | // è·åç¨åºè·¯å¾ä¸çconfigæä»¶å¤¹è·¯å¾ |
| | | std::string UserManager::getConfigFolderPath() { |
| | | char szPath[MAX_PATH]; |
| | | GetModuleFileName(NULL, szPath, MAX_PATH); |
| | | std::string exePath(szPath); |
| | | std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB\\"; |
| | | char szPath[MAX_PATH]; |
| | | GetModuleFileName(NULL, szPath, MAX_PATH); |
| | | std::string exePath(szPath); |
| | | std::string dbDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB\\"; |
| | | |
| | | // æ£æ¥å¹¶å建configæä»¶å¤¹ |
| | | DWORD fileAttr = GetFileAttributes(dbDir.c_str()); |
| | | if (fileAttr == INVALID_FILE_ATTRIBUTES) { |
| | | CreateDirectory(dbDir.c_str(), NULL); |
| | | } |
| | | // æ£æ¥å¹¶å建configæä»¶å¤¹ |
| | | DWORD fileAttr = GetFileAttributes(dbDir.c_str()); |
| | | if (fileAttr == INVALID_FILE_ATTRIBUTES) { |
| | | CreateDirectory(dbDir.c_str(), NULL); |
| | | } |
| | | |
| | | return dbDir; |
| | | return dbDir; |
| | | } |
| | | |
| | | // è·åsession.datæä»¶è·¯å¾ |
| | | // è·åsession.datæä»¶è·¯å¾ |
| | | std::string UserManager::getSessionFilePath() { |
| | | return getConfigFolderPath() + SESSION_FILE; |
| | | return getConfigFolderPath() + SESSION_FILE; |
| | | } |
| | | |
| | | // è·åæ°æ®åºæä»¶è·¯å¾ |
| | | // è·åæ°æ®åºæä»¶è·¯å¾ |
| | | std::string UserManager::getDatabaseFilePath() { |
| | | return getConfigFolderPath() + DATABASE_FILE; |
| | | return getConfigFolderPath() + DATABASE_FILE; |
| | | } |
| | | |
| | | // ç»å½æ¹æ³ |
| | | // ç»å½æ¹æ³ |
| | | bool UserManager::login(const std::string& username, const std::string& password, bool rememberMeFlag) { |
| | | std::string query = "SELECT username, password, role, session_timeout, session_expiration FROM users WHERE username = '" + username + "'"; |
| | | auto result = m_pDB->fetchResults(query); |
| | | std::string query = "SELECT username, password, role, session_timeout, session_expiration FROM users WHERE username = '" + username + "'"; |
| | | auto result = m_pDB->fetchResults(query); |
| | | |
| | | if (result.empty() || result[0][1] != simpleEncryptDecrypt(password, "BandKey")) { |
| | | std::cerr << "Login failed: Invalid username or password." << std::endl; |
| | | return false; |
| | | } |
| | | if (result.empty() || result[0][1] != simpleEncryptDecrypt(password, "BandKey")) { |
| | | std::cerr << "Login failed: Invalid username or password." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | m_strCurrentUser = username; |
| | | m_strCurrentUser = username; |
| | | m_strCurrentPass = password; |
| | | m_enCurrentUserRole = static_cast<UserRole>(std::stoi(result[0][2])); |
| | | m_tmSessionTimeout = std::chrono::minutes(std::stoi(result[0][3])); |
| | | m_tmSessionExpiration = std::chrono::hours(std::stoi(result[0][4])); |
| | | m_isLoggedIn = true; |
| | | m_isRememberMe = rememberMeFlag; |
| | | updateActivityTime(); |
| | | m_tpLastLogin = std::chrono::system_clock::now(); |
| | | m_enCurrentUserRole = static_cast<UserRole>(std::stoi(result[0][2])); |
| | | m_tmSessionTimeout = std::chrono::minutes(std::stoi(result[0][3])); |
| | | m_tmSessionExpiration = std::chrono::hours(std::stoi(result[0][4])); |
| | | m_isLoggedIn = true; |
| | | m_isRememberMe = rememberMeFlag; |
| | | updateActivityTime(); |
| | | m_tpLastLogin = std::chrono::system_clock::now(); |
| | | |
| | | std::string updateLoginTime = "UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE username = '" + username + "'"; |
| | | m_pDB->executeQuery(updateLoginTime); |
| | | std::string updateLoginTime = "UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE username = '" + username + "'"; |
| | | m_pDB->executeQuery(updateLoginTime); |
| | | |
| | | saveSession(); |
| | | return true; |
| | | saveSession(); |
| | | return true; |
| | | } |
| | | |
| | | // ç»åºæ¹æ³ |
| | | // ç»åºæ¹æ³ |
| | | void UserManager::logout() { |
| | | if (m_isLoggedIn) { |
| | | std::cout << "User logged out: " << m_strCurrentUser << std::endl; |
| | | m_strCurrentUser.clear(); |
| | | if (m_isLoggedIn) { |
| | | std::cout << "User logged out: " << m_strCurrentUser << std::endl; |
| | | m_strCurrentUser.clear(); |
| | | m_strCurrentPass.clear(); |
| | | m_isLoggedIn = false; |
| | | m_isRememberMe = false; |
| | | clearSession(); |
| | | } |
| | | m_isLoggedIn = false; |
| | | m_isRememberMe = false; |
| | | clearSession(); |
| | | } |
| | | } |
| | | |
| | | // è¿åå½åç¨æ·çç»å½ç¶æ |
| | | // è¿åå½åç¨æ·çç»å½ç¶æ |
| | | bool UserManager::isLoggedIn() const { |
| | | return m_isLoggedIn; |
| | | return m_isLoggedIn; |
| | | } |
| | | |
| | | // è¿åå½åç¨æ·çè®°ä½ç»å½ç¶æ |
| | | // è¿åå½åç¨æ·çè®°ä½ç»å½ç¶æ |
| | | bool UserManager::isRememberMe() const { |
| | | return m_isRememberMe; |
| | | } |
| | | |
| | | // å建æ°ç¨æ·ï¼ä»
è¶
级管çåææé |
| | | // å建æ°ç¨æ·ï¼ä»
è¶
级管çåææé |
| | | bool UserManager::createUser(const std::string& username, const std::string& password, UserRole role, |
| | | std::chrono::minutes timeout, std::chrono::hours expiration) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can create new users." << std::endl; |
| | | return false; |
| | | } |
| | | std::chrono::minutes timeout, std::chrono::hours expiration) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can create new users." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "INSERT INTO users (username, password, role, session_timeout, session_expiration) VALUES ('" + |
| | | username + "', '" + simpleEncryptDecrypt(password, "BandKey") + "', " + std::to_string(static_cast<int>(role)) + ", " + |
| | | std::to_string(timeout.count()) + ", " + std::to_string(expiration.count()) + ")"; |
| | | return m_pDB->executeQuery(query); |
| | | std::string query = "INSERT INTO users (username, password, role, session_timeout, session_expiration) VALUES ('" + |
| | | username + "', '" + simpleEncryptDecrypt(password, "BandKey") + "', " + std::to_string(static_cast<int>(role)) + ", " + |
| | | std::to_string(timeout.count()) + ", " + std::to_string(expiration.count()) + ")"; |
| | | return m_pDB->executeQuery(query); |
| | | } |
| | | |
| | | // å é¤ç¨æ·ï¼ä»
è¶
级管çåææéï¼ä¸ä¸è½å é¤èªå·± |
| | | // å é¤ç¨æ·ï¼ä»
è¶
级管çåææéï¼ä¸ä¸è½å é¤èªå·± |
| | | bool UserManager::deleteUser(const std::string& username) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can delete users." << std::endl; |
| | | return false; |
| | | } |
| | | if (username == m_strCurrentUser) { |
| | | std::cerr << "SuperAdmin cannot delete their own account." << std::endl; |
| | | return false; |
| | | } |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can delete users." << std::endl; |
| | | return false; |
| | | } |
| | | if (username == m_strCurrentUser) { |
| | | std::cerr << "SuperAdmin cannot delete their own account." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "DELETE FROM users WHERE username = '" + username + "'"; |
| | | return m_pDB->executeQuery(query); |
| | | std::string query = "DELETE FROM users WHERE username = '" + username + "'"; |
| | | return m_pDB->executeQuery(query); |
| | | } |
| | | |
| | | // è·åææç¨æ·ä¿¡æ¯ï¼ä»
è¶
级管çåææé |
| | | // è·åææç¨æ·ä¿¡æ¯ï¼ä»
è¶
级管çåææé |
| | | std::vector<std::vector<std::string>> UserManager::getUsers() { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can retrieve user data." << std::endl; |
| | | return {}; |
| | | } |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can retrieve user data." << std::endl; |
| | | return {}; |
| | | } |
| | | |
| | | // æ¥è¯¢æ´ä¸ªç¨æ·è¡¨ |
| | | std::string query = "SELECT username, password, role, session_timeout, session_expiration, last_login FROM users"; |
| | | std::vector<std::vector<std::string>> results = m_pDB->fetchResults(query); |
| | | for (auto& row : results) { |
| | | row[1] = simpleEncryptDecrypt(row[1], "BandKey"); |
| | | } |
| | | // æ¥è¯¢æ´ä¸ªç¨æ·è¡¨ |
| | | std::string query = "SELECT username, password, role, session_timeout, session_expiration, last_login FROM users"; |
| | | std::vector<std::vector<std::string>> results = m_pDB->fetchResults(query); |
| | | for (auto& row : results) { |
| | | row[1] = simpleEncryptDecrypt(row[1], "BandKey"); |
| | | } |
| | | |
| | | return results; |
| | | return results; |
| | | } |
| | | |
| | | // 设置æ´ä¸ªç¨æ·è¡¨çæ°æ®ï¼ä»
è¶
级管çåææé |
| | | // 设置æ´ä¸ªç¨æ·è¡¨çæ°æ®ï¼ä»
è¶
级管çåææé |
| | | bool UserManager::setUsers(const std::vector<std::vector<std::string>>& usersData) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can set user data." << std::endl; |
| | | return false; |
| | | } |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can set user data." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | // æ¸
ç©ºç¨æ·è¡¨ |
| | | std::string deleteQuery = "DELETE FROM users"; |
| | | if (!m_pDB->executeQuery(deleteQuery)) { |
| | | std::cerr << "Failed to clear the users table." << std::endl; |
| | | return false; |
| | | } |
| | | // æ¸
ç©ºç¨æ·è¡¨ |
| | | std::string deleteQuery = "DELETE FROM users"; |
| | | if (!m_pDB->executeQuery(deleteQuery)) { |
| | | std::cerr << "Failed to clear the users table." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | // æå
¥æ°çç¨æ·æ°æ® |
| | | for (const auto& user : usersData) { |
| | | if (user.size() != 6) { |
| | | std::cerr << "Invalid data format for user. Each user must have 6 fields." << std::endl; |
| | | return false; |
| | | } |
| | | // æå
¥æ°çç¨æ·æ°æ® |
| | | for (const auto& user : usersData) { |
| | | if (user.size() != 6) { |
| | | std::cerr << "Invalid data format for user. Each user must have 6 fields." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string insertQuery = "INSERT INTO users (username, password, role, session_timeout, session_expiration, last_login) VALUES ('" + |
| | | user[0] + "', '" + simpleEncryptDecrypt(user[1], "BandKey") + "', " + user[2] + ", " + user[3] + ", " + user[4] + ", '" + user[5] + "')"; |
| | | std::string insertQuery = "INSERT INTO users (username, password, role, session_timeout, session_expiration, last_login) VALUES ('" + |
| | | user[0] + "', '" + simpleEncryptDecrypt(user[1], "BandKey") + "', " + user[2] + ", " + user[3] + ", " + user[4] + ", '" + user[5] + "')"; |
| | | |
| | | if (!m_pDB->executeQuery(insertQuery)) { |
| | | std::cerr << "Failed to insert user: " << user[0] << std::endl; |
| | | return false; |
| | | } |
| | | } |
| | | if (!m_pDB->executeQuery(insertQuery)) { |
| | | std::cerr << "Failed to insert user: " << user[0] << std::endl; |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | return true; |
| | | } |
| | | |
| | | // ä¿®æ¹ç¨æ·åï¼ä»
è¶
级管çåææé |
| | | // ä¿®æ¹ç¨æ·åï¼ä»
è¶
级管çåææé |
| | | bool UserManager::changeUsername(const std::string& username, const std::string& newUsername) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change usernames." << std::endl; |
| | | return false; |
| | | } |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change usernames." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "UPDATE users SET username = '" + newUsername + "' WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | std::string query = "UPDATE users SET username = '" + newUsername + "' WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | |
| | | // 妿æ¯å½åç»å½ç¨æ·ä¿®æ¹èªå·±çç¨æ·åï¼æ´æ°æååéå¹¶ä¿åä¼è¯æä»¶ |
| | | if (success && m_strCurrentUser == username) { |
| | | m_strCurrentUser = newUsername; |
| | | // 妿æ¯å½åç»å½ç¨æ·ä¿®æ¹èªå·±çç¨æ·åï¼æ´æ°æååéå¹¶ä¿åä¼è¯æä»¶ |
| | | if (success && m_strCurrentUser == username) { |
| | | m_strCurrentUser = newUsername; |
| | | |
| | | // 妿âè®°ä½å¯ç âå·²å¯ç¨ï¼æ´æ°ä¼è¯æä»¶ |
| | | if (m_isRememberMe) { |
| | | saveSession(); |
| | | } |
| | | } |
| | | return success; |
| | | // 妿âè®°ä½å¯ç âå·²å¯ç¨ï¼æ´æ°ä¼è¯æä»¶ |
| | | if (m_isRememberMe) { |
| | | saveSession(); |
| | | } |
| | | } |
| | | return success; |
| | | } |
| | | |
| | | // ä¿®æ¹ç¨æ·å¯ç ï¼ä»
å
许å½åç¨æ·æè¶
级管çåï¼ |
| | | // ä¿®æ¹ç¨æ·å¯ç ï¼ä»
å
许å½åç¨æ·æè¶
级管çåï¼ |
| | | bool UserManager::changePassword(const std::string& username, const std::string& newPassword) { |
| | | if (username != m_strCurrentUser && m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Permission denied: Only the user or SuperAdmin can change passwords." << std::endl; |
| | | return false; |
| | | } |
| | | if (username != m_strCurrentUser && m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Permission denied: Only the user or SuperAdmin can change passwords." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "UPDATE users SET password = '" + simpleEncryptDecrypt(newPassword, "BandKey") + |
| | | "' WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | std::string query = "UPDATE users SET password = '" + simpleEncryptDecrypt(newPassword, "BandKey") + |
| | | "' WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | |
| | | // 妿æ¯å½åç¨æ·ä¿®æ¹èªå·±çå¯ç ï¼éåºç»å½å¹¶æ¸
é¤ä¼è¯æä»¶ |
| | | if (success && m_strCurrentUser == username) { |
| | | logout(); |
| | | std::cout << "Password changed successfully. Please log in again." << std::endl; |
| | | } |
| | | // 妿æ¯å½åç¨æ·ä¿®æ¹èªå·±çå¯ç ï¼éåºç»å½å¹¶æ¸
é¤ä¼è¯æä»¶ |
| | | if (success && m_strCurrentUser == username) { |
| | | logout(); |
| | | std::cout << "Password changed successfully. Please log in again." << std::endl; |
| | | } |
| | | |
| | | return success; |
| | | return success; |
| | | } |
| | | |
| | | // æ´æ¹ç¨æ·è§è²ï¼ä»
è¶
级管çåææé |
| | | // æ´æ¹ç¨æ·è§è²ï¼ä»
è¶
级管çåææé |
| | | bool UserManager::changeUserRole(const std::string& username, UserRole newRole) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change user roles." << std::endl; |
| | | return false; |
| | | } |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change user roles." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | // 鲿¢ç®¡çåæ´æ¹èªå·±çè§è² |
| | | if (m_strCurrentUser == username) { |
| | | std::cerr << "SuperAdmin cannot change their own role." << std::endl; |
| | | return false; |
| | | } |
| | | // 鲿¢ç®¡çåæ´æ¹èªå·±çè§è² |
| | | if (m_strCurrentUser == username) { |
| | | std::cerr << "SuperAdmin cannot change their own role." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "UPDATE users SET role = " + std::to_string(static_cast<int>(newRole)) + |
| | | " WHERE username = '" + username + "'"; |
| | | return m_pDB->executeQuery(query); |
| | | std::string query = "UPDATE users SET role = " + std::to_string(static_cast<int>(newRole)) + |
| | | " WHERE username = '" + username + "'"; |
| | | return m_pDB->executeQuery(query); |
| | | } |
| | | |
| | | // ä¿®æ¹ç¨æ·ç session_timeoutï¼ä»
è¶
级管çåææé |
| | | // ä¿®æ¹ç¨æ·ç session_timeoutï¼ä»
è¶
级管çåææé |
| | | bool UserManager::changeUserSessionTimeout(const std::string& username, int newTimeoutMinutes) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change session timeout." << std::endl; |
| | | return false; |
| | | } |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change session timeout." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "UPDATE users SET session_timeout = " + std::to_string(newTimeoutMinutes) + |
| | | " WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | // 妿æ¯å½åç»å½ç¨æ·ä¿®æ¹èªå·±çè¶
æ¶è®¾ç½®ï¼æ´æ°æååé |
| | | if (success && m_strCurrentUser == username) { |
| | | m_tmSessionTimeout = std::chrono::minutes(newTimeoutMinutes); |
| | | std::string query = "UPDATE users SET session_timeout = " + std::to_string(newTimeoutMinutes) + |
| | | " WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | // 妿æ¯å½åç»å½ç¨æ·ä¿®æ¹èªå·±çè¶
æ¶è®¾ç½®ï¼æ´æ°æååé |
| | | if (success && m_strCurrentUser == username) { |
| | | m_tmSessionTimeout = std::chrono::minutes(newTimeoutMinutes); |
| | | |
| | | if (m_isRememberMe) { |
| | | saveSession(); |
| | | } |
| | | } |
| | | return success; |
| | | if (m_isRememberMe) { |
| | | saveSession(); |
| | | } |
| | | } |
| | | return success; |
| | | } |
| | | |
| | | // ä¿®æ¹ç¨æ·ç session_expirationï¼ä»
è¶
级管çåææé |
| | | // ä¿®æ¹ç¨æ·ç session_expirationï¼ä»
è¶
级管çåææé |
| | | bool UserManager::changeUserSessionExpiration(const std::string& username, int newExpirationHours) { |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change session expiration." << std::endl; |
| | | return false; |
| | | } |
| | | if (m_enCurrentUserRole != UserRole::SuperAdmin) { |
| | | std::cerr << "Only SuperAdmin can change session expiration." << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | std::string query = "UPDATE users SET session_expiration = " + std::to_string(newExpirationHours) + |
| | | " WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | // 妿æ¯å½åç»å½ç¨æ·ä¿®æ¹èªå·±çè¿æè®¾ç½®ï¼æ´æ°æååé |
| | | if (success && m_strCurrentUser == username) { |
| | | m_tmSessionExpiration = std::chrono::hours(newExpirationHours); |
| | | std::string query = "UPDATE users SET session_expiration = " + std::to_string(newExpirationHours) + |
| | | " WHERE username = '" + username + "'"; |
| | | bool success = m_pDB->executeQuery(query); |
| | | // 妿æ¯å½åç»å½ç¨æ·ä¿®æ¹èªå·±çè¿æè®¾ç½®ï¼æ´æ°æååé |
| | | if (success && m_strCurrentUser == username) { |
| | | m_tmSessionExpiration = std::chrono::hours(newExpirationHours); |
| | | |
| | | if (m_isRememberMe) { |
| | | saveSession(); |
| | | } |
| | | } |
| | | return success; |
| | | if (m_isRememberMe) { |
| | | saveSession(); |
| | | } |
| | | } |
| | | return success; |
| | | } |
| | | |
| | | // è·åææç¨æ·åç§° |
| | | // è·åææç¨æ·åç§° |
| | | std::vector<std::string> UserManager::getUsernames() { |
| | | std::vector<std::string> usernames; |
| | | std::string query = "SELECT username FROM users"; |
| | | auto results = m_pDB->fetchResults(query); |
| | | std::vector<std::string> usernames; |
| | | std::string query = "SELECT username FROM users"; |
| | | auto results = m_pDB->fetchResults(query); |
| | | |
| | | for (const auto& row : results) { |
| | | if (!row.empty()) { |
| | | usernames.push_back(row[0]); // è·åç¨æ·ååçå¼ |
| | | } |
| | | } |
| | | for (const auto& row : results) { |
| | | if (!row.empty()) { |
| | | usernames.push_back(row[0]); // è·åç¨æ·ååçå¼ |
| | | } |
| | | } |
| | | |
| | | return usernames; |
| | | return usernames; |
| | | } |
| | | |
| | | // è·åæå®ç¨æ·åçç¨æ·ä¿¡æ¯ |
| | | // è·åæå®ç¨æ·åçç¨æ·ä¿¡æ¯ |
| | | std::vector<std::string> UserManager::getUserInfo(const std::string& username) |
| | | { |
| | | // æå»ºæ¥è¯¢è¯å¥ |
| | | std::ostringstream query; |
| | | query << "SELECT username, password, role, session_timeout, session_expiration, last_login " |
| | | << "FROM users WHERE username = '" << username << "'"; |
| | | // æå»ºæ¥è¯¢è¯å¥ |
| | | std::ostringstream query; |
| | | query << "SELECT username, password, role, session_timeout, session_expiration, last_login " |
| | | << "FROM users WHERE username = '" << username << "'"; |
| | | |
| | | // æ§è¡æ¥è¯¢å¹¶è·åç»æ |
| | | auto results = m_pDB->fetchResults(query.str()); |
| | | if (results.empty()) { |
| | | return {}; |
| | | } |
| | | // æ§è¡æ¥è¯¢å¹¶è·åç»æ |
| | | auto results = m_pDB->fetchResults(query.str()); |
| | | if (results.empty()) { |
| | | return {}; |
| | | } |
| | | |
| | | // è¿åæ¥è¯¢å°ç第ä¸è¡æ°æ® |
| | | return results[0]; |
| | | // è¿åæ¥è¯¢å°ç第ä¸è¡æ°æ® |
| | | return results[0]; |
| | | } |
| | | |
| | | // æ´æ°æåæ´»å¨æ¶é´ï¼ç¨äºæ æä½è¶
æ¶æ£æµ |
| | | // æ´æ°æåæ´»å¨æ¶é´ï¼ç¨äºæ æä½è¶
æ¶æ£æµ |
| | | void UserManager::updateActivityTime() { |
| | | m_tpLastActivity = std::chrono::system_clock::now(); |
| | | std::cout << "Activity updated at: " << std::chrono::system_clock::to_time_t(m_tpLastActivity) << std::endl; |
| | | m_tpLastActivity = std::chrono::system_clock::now(); |
| | | std::cout << "Activity updated at: " << std::chrono::system_clock::to_time_t(m_tpLastActivity) << std::endl; |
| | | } |
| | | |
| | | // è®¾ç½®æ æä½è¶
æ¶æ¶é´ |
| | | // è®¾ç½®æ æä½è¶
æ¶æ¶é´ |
| | | void UserManager::setSessionTimeout(std::chrono::minutes timeout) { |
| | | m_tmSessionTimeout = timeout; |
| | | m_tmSessionTimeout = timeout; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦è¶
è¿æ æä½è¶
æ¶æ¶é´ |
| | | // æ£æ¥æ¯å¦è¶
è¿æ æä½è¶
æ¶æ¶é´ |
| | | bool UserManager::isInactiveTimeout() const { |
| | | auto now = std::chrono::system_clock::now(); |
| | | auto elapsedSeconds = std::chrono::duration_cast<std::chrono::seconds>(now - m_tpLastActivity).count(); |
| | | return elapsedSeconds > m_tmSessionTimeout.count() * 60; |
| | | auto now = std::chrono::system_clock::now(); |
| | | auto elapsedSeconds = std::chrono::duration_cast<std::chrono::seconds>(now - m_tpLastActivity).count(); |
| | | return elapsedSeconds > m_tmSessionTimeout.count() * 60; |
| | | } |
| | | |
| | | // åå§åæ æä½æ£æµï¼å
æ¬è®¾ç½®å
¨å±é¼ æ åé®çé©å |
| | | // åå§åæ æä½æ£æµï¼å
æ¬è®¾ç½®å
¨å±é¼ æ åé®çé©å |
| | | void UserManager::initializeIdleDetection(HWND hwnd) { |
| | | updateActivityTime(); |
| | | m_hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc, (HINSTANCE) nullptr, 0); |
| | | m_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, (HINSTANCE) nullptr, 0); |
| | | ::SetTimer(hwnd, 1, 60000, nullptr); |
| | | updateActivityTime(); |
| | | m_hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc, (HINSTANCE) nullptr, 0); |
| | | m_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, (HINSTANCE) nullptr, 0); |
| | | ::SetTimer(hwnd, 1, 60000, nullptr); |
| | | } |
| | | |
| | | // ç»æ¢æ æä½æ£æµï¼æ¸
é¤é¼ æ åé®çé©å |
| | | // ç»æ¢æ æä½æ£æµï¼æ¸
é¤é¼ æ åé®çé©å |
| | | void UserManager::terminateIdleDetection() { |
| | | if (m_hMouseHook) { |
| | | UnhookWindowsHookEx(m_hMouseHook); |
| | | m_hMouseHook = nullptr; |
| | | } |
| | | if (m_hKeyboardHook) { |
| | | UnhookWindowsHookEx(m_hKeyboardHook); |
| | | m_hKeyboardHook = nullptr; |
| | | } |
| | | ::KillTimer(nullptr, 1); |
| | | if (m_hMouseHook) { |
| | | UnhookWindowsHookEx(m_hMouseHook); |
| | | m_hMouseHook = nullptr; |
| | | } |
| | | if (m_hKeyboardHook) { |
| | | UnhookWindowsHookEx(m_hKeyboardHook); |
| | | m_hKeyboardHook = nullptr; |
| | | } |
| | | ::KillTimer(nullptr, 1); |
| | | } |
| | | |
| | | // è·åå½åç»å½ç¨æ·å |
| | | // è·åå½åç»å½ç¨æ·å |
| | | std::string UserManager::getCurrentUser() const { |
| | | return m_strCurrentUser; |
| | | } |
| | | |
| | | // ä¿®æ¹å½åç»å½ç¨æ·å |
| | | // ä¿®æ¹å½åç»å½ç¨æ·å |
| | | void UserManager::setCurrentUser(const std::string& strName) { |
| | | m_strCurrentUser = strName; |
| | | m_strCurrentUser = strName; |
| | | } |
| | | |
| | | // è·åå½åç»å½ç¨æ·å¯ç |
| | | // è·åå½åç»å½ç¨æ·å¯ç |
| | | std::string UserManager::getCurrentPass() const { |
| | | return m_strCurrentPass; |
| | | } |
| | | |
| | | // ä¿®æ¹å½åç»å½ç¨æ·å¯ç |
| | | // ä¿®æ¹å½åç»å½ç¨æ·å¯ç |
| | | void UserManager::setCurrentPass(const std::string& strPass) { |
| | | m_strCurrentPass = strPass; |
| | | m_strCurrentPass = strPass; |
| | | } |
| | | |
| | | // è·åå½åç»å½ç¨æ·è§è² |
| | | // è·åå½åç»å½ç¨æ·è§è² |
| | | UserRole UserManager::getCurrentUserRole() const { |
| | | return m_enCurrentUserRole; |
| | | } |
| | | |
| | | // ä¿®æ¹å½åç»å½ç¨æ·è§è² |
| | | // ä¿®æ¹å½åç»å½ç¨æ·è§è² |
| | | void UserManager::setCurrentUserRole(UserRole emRole) { |
| | | m_enCurrentUserRole = emRole; |
| | | m_enCurrentUserRole = emRole; |
| | | } |
| | | |
| | | // è·åå½åç»å½ç¨æ·çæ æä½è¶
æ¶æ¶é´ |
| | | // è·åå½åç»å½ç¨æ·çæ æä½è¶
æ¶æ¶é´ |
| | | std::chrono::minutes UserManager::getSessionTimeout() const { |
| | | return m_tmSessionTimeout; |
| | | } |
| | | |
| | | // è·åå½åç»å½ç¨æ·çä¼è¯è¿ææ¶é´ |
| | | // è·åå½åç»å½ç¨æ·çä¼è¯è¿ææ¶é´ |
| | | std::chrono::hours UserManager::getSessionExpiration() const { |
| | | return m_tmSessionExpiration; |
| | | } |
| | | |
| | | // å
¨å±é¼ æ é©ååè°ï¼è®°å½æ´»å¨æ¶é´ |
| | | // å
¨å±é¼ æ é©ååè°ï¼è®°å½æ´»å¨æ¶é´ |
| | | LRESULT CALLBACK UserManager::LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) { |
| | | if (nCode == HC_ACTION) { |
| | | UserManager::getInstance().updateActivityTime(); |
| | | std::cout << "Mouse event detected. Activity time updated." << std::endl; |
| | | } |
| | | return CallNextHookEx(nullptr, nCode, wParam, lParam); |
| | | if (nCode == HC_ACTION) { |
| | | UserManager::getInstance().updateActivityTime(); |
| | | std::cout << "Mouse event detected. Activity time updated." << std::endl; |
| | | } |
| | | return CallNextHookEx(nullptr, nCode, wParam, lParam); |
| | | } |
| | | |
| | | // å
¨å±é®çé©ååè°ï¼è®°å½æ´»å¨æ¶é´ |
| | | // å
¨å±é®çé©ååè°ï¼è®°å½æ´»å¨æ¶é´ |
| | | LRESULT CALLBACK UserManager::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { |
| | | if (nCode == HC_ACTION) { |
| | | UserManager::getInstance().updateActivityTime(); |
| | | std::cout << "Keyboard event detected. Activity time updated." << std::endl; |
| | | } |
| | | return CallNextHookEx(nullptr, nCode, wParam, lParam); |
| | | if (nCode == HC_ACTION) { |
| | | UserManager::getInstance().updateActivityTime(); |
| | | std::cout << "Keyboard event detected. Activity time updated." << std::endl; |
| | | } |
| | | return CallNextHookEx(nullptr, nCode, wParam, lParam); |
| | | } |
| | |
| | | #ifndef USER_MANAGER_H |
| | | #ifndef USER_MANAGER_H |
| | | #define USER_MANAGER_H |
| | | |
| | | #include <string> |
| | |
| | | #include <windows.h> |
| | | #include "Database.h" |
| | | |
| | | // ç¨æ·è§è²å®ä¹ |
| | | // ç¨æ·è§è²å®ä¹ |
| | | enum class UserRole { |
| | | SuperAdmin = 0, // è¶
级管çå |
| | | Engineer, // å·¥ç¨å¸ |
| | | Operator // æä½å |
| | | SuperAdmin = 0, // è¶
级管çåï¼ç³»ç»æé«æéï¼ç®¡çææç¨æ·åæé |
| | | ProcessEngineer, // å¶ç¨å·¥ç¨å¸ï¼è´è´£å·¥èºå¶å®ä¸ä¼å |
| | | EquipmentEngineer,// 设å¤å·¥ç¨å¸ï¼è´è´£è®¾å¤ç»´æ¤ä¸ææ¯æ¯æ |
| | | Operator, // æä½åï¼æ§è¡æ¥å¸¸ç产æä½ |
| | | Unknown // æªç¥è§è²ï¼é»è®¤ææªè¯å«çè§è² |
| | | }; |
| | | |
| | | // ç¨æ·ç®¡çç±»ï¼éç¨å便¨¡å¼ |
| | | // ç¨æ·ç®¡çç±»ï¼éç¨å便¨¡å¼ |
| | | class UserManager { |
| | | public: |
| | | static UserManager& getInstance(); |
| | | static UserManager& getInstance(); |
| | | |
| | | UserManager(const UserManager&) = delete; |
| | | UserManager& operator=(const UserManager&) = delete; |
| | | UserManager(const UserManager&) = delete; |
| | | UserManager& operator=(const UserManager&) = delete; |
| | | |
| | | // æä¾æ°æ®åºè¿æ¥ |
| | | std::unique_ptr<BL::Database>& getDatabaseInstance(); |
| | | // æä¾æ°æ®åºè¿æ¥ |
| | | std::unique_ptr<BL::Database>& getDatabaseInstance(); |
| | | |
| | | // ç¨æ·æä½ |
| | | bool login(const std::string& username, const std::string& password, bool rememberMe = false); |
| | | void logout(); |
| | | bool isLoggedIn() const; |
| | | // ç¨æ·æä½ |
| | | bool login(const std::string& username, const std::string& password, bool rememberMe = false); |
| | | void logout(); |
| | | bool isLoggedIn() const; |
| | | bool isRememberMe() const; |
| | | bool createUser(const std::string& username, const std::string& password, UserRole role, |
| | | std::chrono::minutes timeout = std::chrono::minutes(30), |
| | | std::chrono::hours expiration = std::chrono::hours(72)); |
| | | bool deleteUser(const std::string& username); |
| | | std::vector<std::vector<std::string>> getUsers(); |
| | | bool setUsers(const std::vector<std::vector<std::string>>& usersData); |
| | | bool changeUsername(const std::string& username, const std::string& newUsername); |
| | | bool changePassword(const std::string& username, const std::string& newPassword); |
| | | bool changeUserRole(const std::string& username, UserRole newRole); |
| | | bool changeUserSessionTimeout(const std::string& username, int newTimeoutMinutes); |
| | | bool changeUserSessionExpiration(const std::string& username, int newExpirationHours); |
| | | std::vector<std::string> getUsernames(); |
| | | std::vector<std::string> getUserInfo(const std::string& username); |
| | | bool createUser(const std::string& username, const std::string& password, UserRole role, |
| | | std::chrono::minutes timeout = std::chrono::minutes(30), |
| | | std::chrono::hours expiration = std::chrono::hours(72)); |
| | | bool deleteUser(const std::string& username); |
| | | std::vector<std::vector<std::string>> getUsers(); |
| | | bool setUsers(const std::vector<std::vector<std::string>>& usersData); |
| | | bool changeUsername(const std::string& username, const std::string& newUsername); |
| | | bool changePassword(const std::string& username, const std::string& newPassword); |
| | | bool changeUserRole(const std::string& username, UserRole newRole); |
| | | bool changeUserSessionTimeout(const std::string& username, int newTimeoutMinutes); |
| | | bool changeUserSessionExpiration(const std::string& username, int newExpirationHours); |
| | | std::vector<std::string> getUsernames(); |
| | | std::vector<std::string> getUserInfo(const std::string& username); |
| | | |
| | | // ä¼è¯æä»¶æä½ |
| | | bool loadSession(); // ä»ä¼è¯æä»¶å è½½ä¼è¯ä¿¡æ¯ |
| | | void saveSession(); // ä¿åä¼è¯ä¿¡æ¯å°æä»¶ |
| | | void clearSession(); // æ¸
é¤ä¼è¯æä»¶ |
| | | // ä¼è¯æä»¶æä½ |
| | | bool loadSession(); // ä»ä¼è¯æä»¶å è½½ä¼è¯ä¿¡æ¯ |
| | | void saveSession(); // ä¿åä¼è¯ä¿¡æ¯å°æä»¶ |
| | | void clearSession(); // æ¸
é¤ä¼è¯æä»¶ |
| | | |
| | | // é
ç½®æä»¶å¤¹è·¯å¾ç®¡ç |
| | | static std::string getConfigFolderPath(); |
| | | static std::string getSessionFilePath(); |
| | | static std::string getDatabaseFilePath(); |
| | | // é
ç½®æä»¶å¤¹è·¯å¾ç®¡ç |
| | | static std::string getConfigFolderPath(); |
| | | static std::string getSessionFilePath(); |
| | | static std::string getDatabaseFilePath(); |
| | | |
| | | // æ´æ°æåæ´»å¨æ¶é´ï¼ç¨äºæ æä½è¶
æ¶æ£æµï¼ |
| | | void updateActivityTime(); |
| | | // æ´æ°æåæ´»å¨æ¶é´ï¼ç¨äºæ æä½è¶
æ¶æ£æµï¼ |
| | | void updateActivityTime(); |
| | | |
| | | // è®¾ç½®ç¨æ·çæ æä½è¶
æ¶æ¶é´ |
| | | void setSessionTimeout(std::chrono::minutes timeout); |
| | | // è®¾ç½®ç¨æ·çæ æä½è¶
æ¶æ¶é´ |
| | | void setSessionTimeout(std::chrono::minutes timeout); |
| | | |
| | | // æ£æ¥æ¯å¦æ æä½è¶
æ¶ |
| | | bool isInactiveTimeout() const; |
| | | // æ£æ¥æ¯å¦æ æä½è¶
æ¶ |
| | | bool isInactiveTimeout() const; |
| | | |
| | | // åå§åæ æä½æ£æµï¼è®¾ç½®å
¨å±é©åå宿¶å¨ï¼ |
| | | void initializeIdleDetection(HWND hwnd); |
| | | // åå§åæ æä½æ£æµï¼è®¾ç½®å
¨å±é©åå宿¶å¨ï¼ |
| | | void initializeIdleDetection(HWND hwnd); |
| | | |
| | | // ç»æ¢æ æä½æ£æµï¼æ¸
é¤é©åå宿¶å¨ï¼ |
| | | void terminateIdleDetection(); |
| | | // ç»æ¢æ æä½æ£æµï¼æ¸
é¤é©åå宿¶å¨ï¼ |
| | | void terminateIdleDetection(); |
| | | |
| | | // è·åå½åç»å½ç¨æ·å |
| | | // è·åå½åç»å½ç¨æ·å |
| | | std::string getCurrentUser() const; |
| | | |
| | | // ä¿®æ¹å½åç»å½ç¨æ·å |
| | | void setCurrentUser(const std::string& strName); |
| | | // ä¿®æ¹å½åç»å½ç¨æ·å |
| | | void setCurrentUser(const std::string& strName); |
| | | |
| | | // è·åå½åç»å½ç¨æ·å¯ç |
| | | // è·åå½åç»å½ç¨æ·å¯ç |
| | | std::string getCurrentPass() const; |
| | | |
| | | // ä¿®æ¹å½åç»å½ç¨æ·å¯ç |
| | | void setCurrentPass(const std::string& strPass); |
| | | // ä¿®æ¹å½åç»å½ç¨æ·å¯ç |
| | | void setCurrentPass(const std::string& strPass); |
| | | |
| | | // è·åå½åç»å½ç¨æ·è§è² |
| | | // è·åå½åç»å½ç¨æ·è§è² |
| | | UserRole getCurrentUserRole() const; |
| | | |
| | | // ä¿®æ¹å½åç»å½ç¨æ·è§è² |
| | | void setCurrentUserRole(UserRole emRole); |
| | | // ä¿®æ¹å½åç»å½ç¨æ·è§è² |
| | | void setCurrentUserRole(UserRole emRole); |
| | | |
| | | // è·åå½åç»å½ç¨æ·çæ æä½è¶
æ¶æ¶é´ |
| | | // è·åå½åç»å½ç¨æ·çæ æä½è¶
æ¶æ¶é´ |
| | | std::chrono::minutes getSessionTimeout() const; |
| | | |
| | | // è·åå½åç»å½ç¨æ·çä¼è¯è¿ææ¶é´ |
| | | // è·åå½åç»å½ç¨æ·çä¼è¯è¿ææ¶é´ |
| | | std::chrono::hours getSessionExpiration() const; |
| | | |
| | | private: |
| | | UserManager(); |
| | | ~UserManager(); |
| | | UserManager(); |
| | | ~UserManager(); |
| | | |
| | | // åå§åæ°æ®åºè¿æ¥åç¨æ·è¡¨ |
| | | bool initializeDatabase(); |
| | | // åå§åæ°æ®åºè¿æ¥åç¨æ·è¡¨ |
| | | bool initializeDatabase(); |
| | | |
| | | // åå¸å¯ç ï¼ç¨äºå å¯ç¨æ·å¯ç |
| | | std::string hashPassword(const std::string& password); |
| | | // åå¸å¯ç ï¼ç¨äºå å¯ç¨æ·å¯ç |
| | | std::string hashPassword(const std::string& password); |
| | | |
| | | // å å¯åè§£å¯å½æ° |
| | | std::string simpleEncryptDecrypt(const std::string& data, const std::string& key); |
| | | // å å¯åè§£å¯å½æ° |
| | | std::string simpleEncryptDecrypt(const std::string& data, const std::string& key); |
| | | |
| | | // é®çåé¼ æ é©å彿° |
| | | static LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam); |
| | | static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); |
| | | // é®çåé¼ æ é©å彿° |
| | | static LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam); |
| | | static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); |
| | | |
| | | // 屿§å®ä¹ |
| | | std::string m_strCurrentUser; // å½åç»å½ç¨æ·å |
| | | std::string m_strCurrentPass; // å½åç»å½å¯ç |
| | | UserRole m_enCurrentUserRole; // å½åç»å½ç¨æ·è§è² |
| | | bool m_isLoggedIn; // æ¯å¦å·²ç»å½ |
| | | bool m_isRememberMe; // æ¯å¦è®°ä½ç»å½ç¶æ |
| | | // 屿§å®ä¹ |
| | | std::string m_strCurrentUser; // å½åç»å½ç¨æ·å |
| | | std::string m_strCurrentPass; // å½åç»å½å¯ç |
| | | UserRole m_enCurrentUserRole; // å½åç»å½ç¨æ·è§è² |
| | | bool m_isLoggedIn; // æ¯å¦å·²ç»å½ |
| | | bool m_isRememberMe; // æ¯å¦è®°ä½ç»å½ç¶æ |
| | | |
| | | std::chrono::time_point<std::chrono::system_clock> m_tpLastLogin; // 䏿¬¡ç»å½æ¶é´ |
| | | std::chrono::time_point<std::chrono::system_clock> m_tpLastActivity; // æåæ´»å¨æ¶é´ |
| | | std::chrono::minutes m_tmSessionTimeout; // æ æä½è¶
æ¶æ¶é´ |
| | | std::chrono::hours m_tmSessionExpiration; // ä¼è¯è¿ææ¶é´ |
| | | HHOOK m_hMouseHook; // é¼ æ é©å奿 |
| | | HHOOK m_hKeyboardHook; // é®çé©å奿 |
| | | std::chrono::time_point<std::chrono::system_clock> m_tpLastLogin; // 䏿¬¡ç»å½æ¶é´ |
| | | std::chrono::time_point<std::chrono::system_clock> m_tpLastActivity; // æåæ´»å¨æ¶é´ |
| | | std::chrono::minutes m_tmSessionTimeout; // æ æä½è¶
æ¶æ¶é´ |
| | | std::chrono::hours m_tmSessionExpiration; // ä¼è¯è¿ææ¶é´ |
| | | HHOOK m_hMouseHook; // é¼ æ é©å奿 |
| | | HHOOK m_hKeyboardHook; // é®çé©å奿 |
| | | |
| | | std::unique_ptr<BL::Database> m_pDB; // æ°æ®åºæ¥å£ |
| | | std::unique_ptr<BL::Database> m_pDB; // æ°æ®åºæ¥å£ |
| | | }; |
| | | |
| | | #endif // USER_MANAGER_H |
| | |
| | | m_gridUserManager.ExpandLastColumn(); // æåä¸åå¡«å
ç½æ ¼ |
| | | |
| | | m_mapRoleDescriptions.clear(); |
| | | m_mapRoleDescriptions.emplace(_T("管çå"), _T("ç®¡çææç¨æ·ï¼åé
æé")); |
| | | m_mapRoleDescriptions.emplace(_T("å·¥ç¨å¸"), _T("ç»´æ¤ç³»ç»ï¼è§£å³ææ¯é®é¢")); |
| | | m_mapRoleDescriptions.emplace(_T("æä½å"), _T("æ§è¡æ¥å¸¸æä½ä»»å¡")); |
| | | m_mapRoleDescriptions.emplace(_T("管çå"), _T("ç®¡çææç¨æ·è´¦æ·ï¼åé
åè°æ´æéï¼è´è´£ç³»ç»å®å
¨ä¸æ´ä½è¿è¡")); |
| | | m_mapRoleDescriptions.emplace(_T("å¶ç¨å·¥ç¨å¸"), _T("è´è´£ç产工èºçå¶å®ãä¼å䏿¹è¿ï¼ç¡®ä¿å·¥èºç¨³å®åè¯çæå")); |
| | | m_mapRoleDescriptions.emplace(_T("设å¤å·¥ç¨å¸"), _T("ç»´æ¤åä¿å
»è®¾å¤ï¼å¤çæ
éï¼ä¿é设å¤ç¨³å®è¿è¡ï¼å䏿æ¯å级")); |
| | | m_mapRoleDescriptions.emplace(_T("æä½å"), _T("æç
§æ åæµç¨æ§è¡æ¥å¸¸æä½ä»»å¡ï¼çæ§ç产ç¶åµï¼åæ¶åé¦å¼å¸¸")); |
| | | |
| | | FillUserManager(); |
| | | } |
| | |
| | | |
| | | CStringArray permissions; |
| | | permissions.Add(_T("管çå")); |
| | | permissions.Add(_T("å·¥ç¨å¸")); |
| | | permissions.Add(_T("å¶ç¨å·¥ç¨å¸")); |
| | | permissions.Add(_T("设å¤å·¥ç¨å¸")); |
| | | permissions.Add(_T("æä½å")); |
| | | |
| | | int nCols = m_gridUserManager.GetColumnCount(); |
| | | for (int i = 1; i < m_gridUserManager.GetRowCount(); ++i) { |
| | | m_gridUserManager.SetItemState(i, 0, GVIS_READONLY); // 第ä¸ååªè¯» |
| | | m_gridUserManager.SetItemState(i, 0, GVIS_READONLY); // 第ä¸ååªè¯» |
| | | m_gridUserManager.SetItemState(i, nCols - 2, GVIS_READONLY); // åæ°ç¬¬äºååªè¯» |
| | | m_gridUserManager.SetItemState(i, nCols - 1, GVIS_READONLY); // æåä¸ååªè¯» |
| | | |
| | |
| | | pCell->SetOptions(permissions); |
| | | pCell->SetStyle(CBS_DROPDOWNLIST); |
| | | |
| | | CString cstrRole = m_gridUserManager.GetItemText(i, 3); |
| | | int nRole = _ttoi(cstrRole); |
| | | if (nRole < 0 || nRole > 2) { |
| | | int nRole = _ttoi(m_gridUserManager.GetItemText(i, 3)); |
| | | if (nRole < 0 || nRole > 3) { |
| | | CString cstrMessage; |
| | | cstrMessage.Format(_T("ç¨æ· [%s]ï¼æéå¼å¸¸ï¼å°è®¾ç½®ææä½åï¼"), m_gridUserManager.GetItemText(i, 1)); |
| | | AfxMessageBox(cstrMessage); |
| | | nRole = 2; |
| | | nRole = 3; |
| | | } |
| | | |
| | | m_gridUserManager.SetItemText(i, 3, permissions.GetAt(nRole)); |
| | |
| | | // 第ååè®¾ç½®ï¼æéåï¼ä¸ºä¸ææ¡ |
| | | CStringArray permissions; |
| | | permissions.Add(_T("管çå")); |
| | | permissions.Add(_T("å·¥ç¨å¸")); |
| | | permissions.Add(_T("å¶ç¨å·¥ç¨å¸")); |
| | | permissions.Add(_T("设å¤å·¥ç¨å¸")); |
| | | permissions.Add(_T("æä½å")); |
| | | |
| | | if (pGridCtrl->SetCellType(newRowIndex, 3, RUNTIME_CLASS(CGridCellCombo))) { |
| | |
| | | |
| | | CStringArray permissions; |
| | | permissions.Add(_T("管çå")); |
| | | permissions.Add(_T("å·¥ç¨å¸")); |
| | | permissions.Add(_T("å¶ç¨å·¥ç¨å¸")); |
| | | permissions.Add(_T("设å¤å·¥ç¨å¸")); |
| | | permissions.Add(_T("æä½å")); |
| | | |
| | | if (m_gridUserManager.SetCellType(row, 3, RUNTIME_CLASS(CGridCellCombo))) { |
| | |
| | | if (j == 3) { |
| | | if (cellText == _T("管çå")) |
| | | cellString = "0"; |
| | | else if (cellText == _T("å·¥ç¨å¸")) |
| | | else if (cellText == _T("å¶ç¨å·¥ç¨å¸")) |
| | | cellString = "1"; |
| | | else if (cellText == _T("设å¤å·¥ç¨å¸")) |
| | | cellString = "2"; |
| | | else if (cellText == _T("æä½å")) |
| | | cellString = "2"; |
| | | cellString = "3"; |
| | | else |
| | | cellString = "2"; |
| | | cellString = "3"; |
| | | } |
| | | |
| | | rowData.push_back(cellString); |