#include "stdafx.h" #include #include #include // µ¥Àý»ñÈ¡ RecipeManager& RecipeManager::getInstance() { static RecipeManager instance; return instance; } // ¹¹Ô캯Êý RecipeManager::RecipeManager() : m_recipeFolder("Recipe") {} // ÉèÖÃÅä·½Îļþ¼Ð void RecipeManager::setRecipeFolder(const std::string& folderPath) { m_recipeFolder = folderPath; } // ¼ÓÔØÅä·½£¨Èç¹ûÎļþ²»´æÔÚ£¬¼ÓÔØÄ¬ÈÏÊý¾Ý£© bool RecipeManager::loadRecipe(const std::string& recipeName) { std::string filePath = m_recipeFolder + "/" + recipeName + ".xml"; pugi::xml_document doc; if (!doc.load_file(filePath.c_str())) { std::cerr << "Recipe file not found: " << filePath << ". Loading default recipe." << std::endl; generateDefaultRecipe(); return false; // Îļþ²»´æÔÚ£¬µ«¼ÓÔØÁËĬÈÏÊý¾Ý } m_axes.clear(); auto recipe = doc.child("Recipe"); for (auto axisNode : recipe.child("Axes").children("Axis")) { AxisInfo axisInfo; axisInfo.id = axisNode.attribute("id").as_int(); axisInfo.number = axisNode.attribute("number").value(); axisInfo.description = axisNode.attribute("description").value(); axisInfo.startAddress = axisNode.attribute("start_address").value(); // ¼ÓÔØ ValueRange Öµ axisInfo.jogDistance = ValueRange( axisNode.child("jog_distance").attribute("min").as_double(), axisNode.child("jog_distance").attribute("max").as_double(), axisNode.child("jog_distance").attribute("current").as_double() ); axisInfo.manualSpeed = ValueRange( axisNode.child("manual_speed").attribute("min").as_double(), axisNode.child("manual_speed").attribute("max").as_double(), axisNode.child("manual_speed").attribute("current").as_double() ); axisInfo.autoSpeed = ValueRange( axisNode.child("auto_speed").attribute("min").as_double(), axisNode.child("auto_speed").attribute("max").as_double(), axisNode.child("auto_speed").attribute("current").as_double() ); axisInfo.accelerationTime = ValueRange( axisNode.child("acceleration_time").attribute("min").as_double(), axisNode.child("acceleration_time").attribute("max").as_double(), axisNode.child("acceleration_time").attribute("current").as_double() ); axisInfo.decelerationTime = ValueRange( axisNode.child("deceleration_time").attribute("min").as_double(), axisNode.child("deceleration_time").attribute("max").as_double(), axisNode.child("deceleration_time").attribute("current").as_double() ); // ¼ÓÔØ PositionRange Öµ for (auto positionNode : axisNode.child("Positions").children("Position")) { std::string description = positionNode.attribute("description").value(); ValueRange positionRange( positionNode.attribute("min").as_double(), positionNode.attribute("max").as_double(), positionNode.attribute("current").as_double() ); axisInfo.positions.emplace_back(PositionRange(description, positionRange)); } m_axes[axisInfo.id] = axisInfo; } return true; } // ±£´æÅä·½ bool RecipeManager::saveRecipe(const std::string& recipeName) { // Éú³ÉÎļþ·¾¶ std::string filePath = m_recipeFolder + "/" + recipeName + ".xml"; // ´´½¨ XML Îĵµ¶ÔÏó pugi::xml_document doc; // Èç¹ûÖáÊý¾ÝΪ¿Õ£¬Éú³ÉĬÈÏÅä·½ if (m_axes.empty()) { generateDefaultRecipe(); } // Ìí¼ÓÅä·½¸ù½Úµã auto recipe = doc.append_child("Recipe"); // Ìí¼ÓÖáÁбí½Úµã auto axesNode = recipe.append_child("Axes"); // ±éÀúËùÓÐÖáÊý¾Ý²¢Ð´Èë XML for (const auto& axisEntry : m_axes) { const AxisInfo& axisInfo = axisEntry.second; auto axisNode = axesNode.append_child("Axis"); axisNode.append_attribute("id") = axisInfo.id; axisNode.append_attribute("number") = axisInfo.number.c_str(); axisNode.append_attribute("description") = axisInfo.description.c_str(); axisNode.append_attribute("start_address") = axisInfo.startAddress.c_str(); // ±£´æ ValueRange Öµ auto jog_distance = axisNode.append_child("jog_distance"); jog_distance.append_attribute("min") = axisInfo.jogDistance.minValue; jog_distance.append_attribute("max") = axisInfo.jogDistance.maxValue; jog_distance.append_attribute("current") = axisInfo.jogDistance.currentValue; auto manual_speed = axisNode.append_child("manual_speed"); manual_speed.append_attribute("min") = axisInfo.manualSpeed.minValue; manual_speed.append_attribute("max") = axisInfo.manualSpeed.maxValue; manual_speed.append_attribute("current") = axisInfo.manualSpeed.currentValue; auto auto_speed = axisNode.append_child("auto_speed"); auto_speed.append_attribute("min") = axisInfo.autoSpeed.minValue; auto_speed.append_attribute("max") = axisInfo.autoSpeed.maxValue; auto_speed.append_attribute("current") = axisInfo.autoSpeed.currentValue; auto acceleration_time = axisNode.append_child("acceleration_time"); acceleration_time.append_attribute("min") = axisInfo.accelerationTime.minValue; acceleration_time.append_attribute("max") = axisInfo.accelerationTime.maxValue; acceleration_time.append_attribute("current") = axisInfo.accelerationTime.currentValue; auto deceleration_time = axisNode.append_child("deceleration_time"); deceleration_time.append_attribute("min") = axisInfo.decelerationTime.minValue; deceleration_time.append_attribute("max") = axisInfo.decelerationTime.maxValue; deceleration_time.append_attribute("current") = axisInfo.decelerationTime.currentValue; // ±£´æ PositionRange Öµ auto positionsNode = axisNode.append_child("Positions"); for (const auto& position : axisInfo.positions) { auto positionNode = positionsNode.append_child("Position"); positionNode.append_attribute("description") = position.description.c_str(); positionNode.append_attribute("min") = position.range.minValue; positionNode.append_attribute("max") = position.range.maxValue; positionNode.append_attribute("current") = position.range.currentValue; } } // ±£´æ XML Îļþ return doc.save_file(filePath.c_str()); } // Éú³ÉĬÈÏÅä·½ void RecipeManager::generateDefaultRecipe() { m_axes.clear(); for (int axisId = 1; axisId <= 12; ++axisId) { AxisInfo axisInfo; axisInfo.id = axisId; axisInfo.number = "M100-M" + std::to_string(axisId); axisInfo.description = "Default_Axis" + std::to_string(axisId); axisInfo.startAddress = "ZR" + std::to_string(10000 + (axisId - 1) * 300); // ÉèÖÃĬÈ쵀 ValueRange axisInfo.jogDistance = ValueRange(1.0, 10.0, 1.0); axisInfo.manualSpeed = ValueRange(1.0, 100.0, 10.0); axisInfo.autoSpeed = ValueRange(5.0, 200.0, 50.0); axisInfo.accelerationTime = ValueRange(1.0, 10.0, 1.0); axisInfo.decelerationTime = ValueRange(1.0, 10.0, 1.0); // Ìí¼Ó¶¨Î»µã²¢ÉèÖÃĬÈϵÄ×îСֵºÍ×î´óÖµ for (int posId = 1; posId <= 25; ++posId) { double minPos = posId * 5.0; double maxPos = posId * 20.0; axisInfo.positions.emplace_back(PositionRange("Position " + std::to_string(posId), ValueRange(minPos, maxPos, posId * 10.0))); } m_axes[axisId] = axisInfo; } } // »ñÈ¡ËùÓÐÖáÐÅÏ¢ const std::map& RecipeManager::getAxes() const { return m_axes; } // »ñÈ¡µ¥¸öÖáÐÅÏ¢ AxisInfo RecipeManager::getAxis(int axisId) const { auto it = m_axes.find(axisId); if (it != m_axes.end()) { return it->second; // Èç¹ûÕÒµ½ÁËÖᣬ·µ»ØÆäÏêϸÐÅÏ¢ } // Èç¹ûûÓÐÕÒµ½¸ÃÖᣬ·µ»ØÒ»¸öĬÈϵÄÎÞЧ AxisInfo return AxisInfo{ -1, "", "", "", ValueRange(), ValueRange(), ValueRange(), ValueRange(), ValueRange(), {} }; } // ¸üÐÂÖáÐÅÏ¢ bool RecipeManager::updateAxis(const AxisInfo& axisInfo) { if (m_axes.find(axisInfo.id) == m_axes.end()) { return false; // Öá²»´æÔÚ } m_axes[axisInfo.id] = axisInfo; return true; } // Ìí¼ÓеÄÖáÐÅÏ¢ bool RecipeManager::addAxis(const AxisInfo& axisInfo) { if (m_axes.find(axisInfo.id) != m_axes.end()) { return false; // ÖáÒÑ´æÔÚ } m_axes[axisInfo.id] = axisInfo; return true; } // ɾ³ýÖáÐÅÏ¢ bool RecipeManager::deleteAxis(int axisId) { return m_axes.erase(axisId) > 0; } // »ñÈ¡ËùÓÐÖá±àºÅ std::vector RecipeManager::getAllAxisID() const { std::vector axisNumbers; for (const auto& axis : m_axes) { int axisId = axis.first; axisNumbers.push_back(axisId); } return axisNumbers; } // »ñȡָ¶¨Ò³µÄ¶¨Î»µã std::vector RecipeManager::getPositions(int axisId, int pageNumber, int pageSize) const { std::vector result; // ¼ì²éÖáÊÇ·ñ´æÔÚ auto it = m_axes.find(axisId); if (it == m_axes.end()) { return result; // Èç¹ûÖá ID ²»´æÔÚ£¬·µ»Ø¿Õ½á¹û } // »ñȡָ¶¨ÖáµÄËùÓж¨Î»µã const auto& positions = it->second.positions; // È·¶¨·ÖÒ³·¶Î§ int startIndex = (pageNumber - 1) * pageSize; int endIndex = startIndex + pageSize; // ±éÀú¶¨Î»µã£¬°´·ÖÒ³ÌáÈ¡Êý¾Ý int index = 0; for (const auto& pos : positions) { const PositionRange& position = pos; // ¶¨Î»µã°üº¬ÃèÊö¡¢Î»Öá¢×îСֵ¡¢×î´óÖµºÍµ±Ç°Öµ if (index >= startIndex && index < endIndex) { result.push_back(position); // Ìí¼ÓÍêÕûµÄ PositionRange ¶ÔÏó } ++index; if (index >= endIndex) { break; // ´ïµ½·ÖÒ³½áÊøµã } } return result; } // »ñȡָ¶¨ÖáµÄ¶¨Î»µã PositionRange RecipeManager::getPositionByIndex(int axisId, int pageNumber, int pageSize, int currentIndex) const { // ¼ì²éÖáÊÇ·ñ´æÔÚ auto it = m_axes.find(axisId); if (it == m_axes.end()) { return PositionRange(); // Öá²»´æÔÚ£¬·µ»ØÄ¬ÈϹ¹ÔìµÄ PositionRange£¨ÎÞЧµÄ¶¨Î»µã£© } // »ñȡָ¶¨ÖáµÄËùÓж¨Î»µã const auto& positions = it->second.positions; // È·¶¨·ÖÒ³·¶Î§ int startIndex = (pageNumber - 1) * pageSize; int endIndex = startIndex + pageSize; // Èç¹û currentIndex ³¬¹ýÁ˵±Ç°Ò³µÄ·¶Î§£¬·µ»ØÎÞЧµÄ PositionRange if (currentIndex < 0 || currentIndex >= pageSize || currentIndex + startIndex >= positions.size()) { return PositionRange(); // ·µ»ØÎÞЧµÄ¶¨Î»µã } // ·µ»ØÖ¸¶¨¶¨Î»µã£¨¿¼ÂÇ·ÖÒ³£© return positions[startIndex + currentIndex]; }