| | |
| | | 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() { |
| | |
| | | |
| | | for (const auto& device : recipe.vecDeviceList) { |
| | | std::ostringstream devSql; |
| | | devSql << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id) VALUES ('" |
| | | 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.nRecipeID << ", '" |
| | | << device.strRecipeName << "');"; |
| | | |
| | | |
| | | if (!m_pDB->executeQuery(devSql.str())) { |
| | | std::cerr << "[AddRecipe] Failed to insert device mapping: " << device.nDeviceID << std::endl; |
| | |
| | | |
| | | // 插入设备记录 |
| | | std::ostringstream oss; |
| | | oss << "INSERT OR REPLACE INTO recipe_devices (ppid, device_id, device_name, recipe_id) VALUES ('" |
| | | 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.nRecipeID << ", '" |
| | | << device.strRecipeName << "');"; |
| | | |
| | | std::lock_guard<std::recursive_mutex> lock(m_mutex); |
| | | return m_pDB->executeQuery(oss.str()); |
| | |
| | | info.strCreateTime = row[2]; |
| | | |
| | | std::ostringstream devQuery; |
| | | devQuery << "SELECT device_id, device_name, recipe_id FROM recipe_devices WHERE ppid = '" << info.strPPID << "';"; |
| | | 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; |
| | | dr.strPPID = info.strPPID; |
| | | 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; |
| | |
| | | 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 + "';"); |
| | | 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; |
| | | dr.strPPID = ppid; |
| | | 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; |
| | |
| | | return m_pDB->executeQuery(query.str()); |
| | | } |
| | | |
| | | bool RecipeManager::addDeviceRecipe(const std::string& deviceName, int nRecipeID, const std::string& strRecipeName) { |
| | | if (!m_pDB || deviceName.empty() || nRecipeID <= 0 || strRecipeName.empty()) { |
| | | return false; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "CREATE TABLE IF NOT EXISTS " << deviceName << "_Recipes (" |
| | | << "recipe_id INTEGER PRIMARY KEY, " |
| | | << "recipe_name TEXT NOT NULL" |
| | | << ");"; |
| | | m_pDB->executeQuery(sql.str()); |
| | | |
| | | std::ostringstream ins; |
| | | ins << "INSERT OR REPLACE INTO " << deviceName << "_Recipes (recipe_id, recipe_name) VALUES (" |
| | | << nRecipeID << ", '" << strRecipeName << "');"; |
| | | |
| | | std::lock_guard<std::recursive_mutex> lk(m_mutex); |
| | | return m_pDB->executeQuery(ins.str()); |
| | | } |
| | | |
| | | bool RecipeManager::updateDeviceRecipe(const std::string& deviceName, int nRecipeID, const std::string& newName) { |
| | | if (!m_pDB || deviceName.empty() || nRecipeID <= 0 || newName.empty()) { |
| | | return false; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "UPDATE " << deviceName << "_Recipes SET recipe_name='" << newName |
| | | << "' WHERE recipe_id=" << nRecipeID << ";"; |
| | | |
| | | std::lock_guard<std::recursive_mutex> lk(m_mutex); |
| | | return m_pDB->executeQuery(sql.str()); |
| | | } |
| | | |
| | | std::string RecipeManager::getDeviceRecipeName(const std::string& deviceName, int nRecipeID) { |
| | | if (!m_pDB || deviceName.empty() || nRecipeID <= 0) { |
| | | return ""; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "SELECT recipe_name FROM " << deviceName << "_Recipes " |
| | | << "WHERE recipe_id=" << nRecipeID << " 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& deviceName, int nRecipeID) { |
| | | if (!m_pDB || deviceName.empty() || nRecipeID <= 0) { |
| | | return false; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "DELETE FROM " << deviceName << "_Recipes WHERE recipe_id=" << nRecipeID << ";"; |
| | | |
| | | 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& deviceName) { |
| | | std::vector<std::pair<int, std::string>> out; |
| | | if (!m_pDB || deviceName.empty()) { |
| | | return out; |
| | | } |
| | | |
| | | std::ostringstream sql; |
| | | sql << "SELECT recipe_id, recipe_name FROM " << deviceName << "_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; |
| | |
| | | recipe.strDescription = "Main Board Burn-in"; |
| | | |
| | | recipe.vecDeviceList = { |
| | | {1, 101, "P1001","Burner A"}, |
| | | {2, 102, "P1001", "Burner B"} |
| | | {9, 101, "VacuumBake", "VacuumBake"}, |
| | | {10, 102, "Bonder1", "Bonder1"}, |
| | | {11, 103, "Bonder2", "Bonder2"} |
| | | }; |
| | | |
| | | 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) { |
| | |
| | | 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, ','); |
| | | |
| | | dev.strPPID = ppid; |
| | | auto& recipe = recipeMap[ppid]; |
| | | recipe.strPPID = ppid; |
| | | recipe.strDescription = description; |
| | |
| | | return false; |
| | | } |
| | | |
| | | file << "PPID,DeviceID,DeviceName,RecipeID,Description,CreateTime\n"; |
| | | file << "PPID,DeviceID,DeviceName,RecipeID,RecipeName,Description,CreateTime\n"; |
| | | auto recipes = getAllRecipes(); |
| | | for (const auto& recipe : recipes) { |
| | | for (const auto& dev : recipe.vecDeviceList) { |
| | |
| | | << dev.nDeviceID << "," |
| | | << dev.strDeviceName << "," |
| | | << dev.nRecipeID << "," |
| | | << dev.strRecipeName << "," |
| | | << recipe.strDescription << "," |
| | | << recipe.strCreateTime << "\n"; |
| | | } |