diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 66bf41019a..524a69403f 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3680,21 +3680,24 @@ bool GUI_App::select_printer_preset(const Preset* preset) bool GUI_App::select_printer_from_connect(const std::string& msg) { // parse message - std::vector compatible_printers; - plater()->get_user_account()->fill_compatible_printers_from_json(msg, compatible_printers); - std::string model_name; - if (compatible_printers.empty()) { - // TODO: This should go away when compatible printers gives right information. + std::string model_name = plater()->get_user_account()->get_keyword_from_json(msg, "printer_model"); + if (model_name.empty()) { + std::vector compatible_printers; + plater()->get_user_account()->fill_compatible_printers_from_json(msg, compatible_printers); + if (!compatible_printers.empty()) { + model_name = compatible_printers.front(); + } + } + // TODO: This should go away when compatible printers gives right information. + if (model_name.empty()) { model_name = plater()->get_user_account()->get_model_from_json(msg); } - else { - model_name = compatible_printers.front(); + if (model_name.empty()) { + BOOST_LOG_TRIVIAL(error) << "Failed to select printer from Connect. Printer_model is empty."; + return false; } std::string nozzle = plater()->get_user_account()->get_nozzle_from_json(msg); - assert(!model_name.empty()); - if (model_name.empty()) - return false; - + BOOST_LOG_TRIVIAL(info) << "Select printer from Connect. Model: " << model_name << "nozzle: " << nozzle; // select printer const Preset* printer_preset = preset_bundle->printers.find_system_preset_by_model_and_variant(model_name, nozzle); bool is_installed = printer_preset && select_printer_preset(printer_preset); @@ -3704,82 +3707,92 @@ bool GUI_App::select_printer_from_connect(const std::string& msg) GUI::format(_L("Selected Printer:\n%1%"), printer_preset->name)) : GUI::format(_L("Printer not found:\n%1%"), model_name); this->plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectPrinterFromConnect); - this->plater()->get_notification_manager()->push_notification(NotificationType::SelectPrinterFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + this->plater()->get_notification_manager()->push_notification( + NotificationType::SelectPrinterFromConnect + , printer_preset ? NotificationManager::NotificationLevel::ImportantNotificationLevel : NotificationManager::NotificationLevel::WarningNotificationLevel + , out); return printer_preset; } -bool GUI_App::select_filament_preset(const Preset* preset) +bool GUI_App::select_filament_preset(const Preset* preset, size_t extruder_index) { assert(preset && preset->is_compatible); if (!preset->is_visible) { - size_t preset_id = preset_bundle->filaments.get_preset_idx_by_name(preset->name); - assert(preset_id != size_t(-1)); - preset_bundle->filaments.select_preset(preset_id); + //size_t preset_id = preset_bundle->filaments.get_preset_idx_by_name(preset->name); + //assert(preset_id != size_t(-1)); + //preset_bundle->filaments.select_preset(preset_id); + bool r = preset_bundle->extruders_filaments[extruder_index].select_filament(preset->name); + assert(r); } return get_tab(Preset::Type::TYPE_FILAMENT)->select_preset(preset->name); } -void GUI_App::select_filament_from_connect(const std::string& msg) +void GUI_App::search_and_select_filaments(const std::string& material, size_t extruder_index, std::string& out_message) { - - // parse message - std::string desired_type; - desired_type = plater()->get_user_account()->get_keyword_from_json(msg, "material"); - if (desired_type.empty()) { + const DynamicPrintConfig& config = preset_bundle->extruders_filaments[extruder_index].get_selected_preset()->config; + // selected is ok + if (config.has("filament_type") && config.option("filament_type")->serialize() == material) { return; } - // test if currently selected is same type - std::string selected_type = preset_bundle->filaments.get_selected_preset().config.option("filament_type")->serialize(); - if (selected_type == desired_type) { - return; - } - // find first filament with suitable type - for (const auto& filament_preset : preset_bundle->filaments) { - if (filament_preset.is_visible - && !filament_preset.vendor->templates_profile - && filament_preset.is_compatible - && filament_preset.config.option("filament_type")->serialize() == desired_type - && select_filament_preset(&filament_preset)) + // find first installed compatible filament with suitable type and select it + for (const auto& filament : preset_bundle->extruders_filaments[extruder_index]) { + if (filament.is_compatible + && !filament.preset->is_default + && filament.preset->is_visible + && !filament.preset->vendor->templates_profile + && filament.preset->config.has("filament_type") + && filament.preset->config.option("filament_type")->serialize() == material + && select_filament_preset(filament.preset, extruder_index) + ) { - std::string out = GUI::format(_L("Selected Filament:\n%1%"), filament_preset.name); - plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); - plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + out_message += /*(extruder_count == 1) + ? GUI::format(_L("Selected Filament:\n%1%"), filament_preset.preset->name) + : */GUI::format(_L("Extruder %1%: Selected Filament %2%\n"), extruder_index + 1, filament.preset->name); return; } } // find profile to install - // first try finding Prusament - for (const auto& filament_preset : preset_bundle->filaments) { - if (!filament_preset.vendor->templates_profile - && filament_preset.is_compatible - && filament_preset.config.option("filament_type")->serialize() == desired_type - && filament_preset.name.compare(0, 9, "Prusament") == 0 - && select_filament_preset(&filament_preset)) + // try finding Prusament + for (const auto& filament : preset_bundle->extruders_filaments[extruder_index]) { + if (filament.is_compatible + && !filament.preset->is_default + && !filament.preset->vendor->templates_profile + && filament.preset->config.has("filament_type") + && filament.preset->config.option("filament_type")->serialize() == material + && filament.preset->name.compare(0, 9, "Prusament") == 0 + && select_filament_preset(filament.preset, 0)) { - std::string out = GUI::format(_L("Installed and Selected Filament:\n%1%"), filament_preset.name); - plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); - plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + out_message += GUI::format(_L("Extruder %1%: Selected and Installed Filament %2%\n"), extruder_index + 1, filament.preset->name); return; } } - // then just any compatible - for (const auto& filament_preset : preset_bundle->filaments) { - if (!filament_preset.vendor->templates_profile - && filament_preset.is_compatible - && filament_preset.config.option("filament_type")->serialize() == desired_type - && select_filament_preset(&filament_preset)) - { - std::string out = GUI::format(_L("Installed and Selected Filament:\n%1%"), filament_preset.name); - plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); - plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); - return; - } + out_message += GUI::format(_L("Extruder %2%: Failed to Find and Select Filament type: %1%\n"), material, extruder_index + 1); +} + +void GUI_App::select_filament_from_connect(const std::string& msg) +{ + // parse message + std::vector materials; + plater()->get_user_account()->fill_material_from_json(msg, materials); + if (materials.empty()) { + BOOST_LOG_TRIVIAL(error) << "Failed to select filament from Connect. No material data."; + return; + } + // test if currently selected is same type + size_t extruder_count = preset_bundle->extruders_filaments.size(); + if (extruder_count != materials.size()) { + BOOST_LOG_TRIVIAL(error) << format("Failed to select filament from Connect. Selected printer has %1% extruders while data from Connect contains %2% materials.", extruder_count, materials.size()); + return; + } + std::string notification_text; + for (size_t i = 0; i < extruder_count; i++) { + search_and_select_filaments(materials[i], i, notification_text); } - // no filamet found - std::string out = GUI::format(_L("Failed to find and select filament type:\n%1%"), desired_type); plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); - plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, notification_text); + return; + } void GUI_App::handle_connect_request_printer_pick(const std::string& msg) @@ -3788,10 +3801,11 @@ void GUI_App::handle_connect_request_printer_pick(const std::string& msg) // return to plater this->mainframe->select_tab(size_t(0)); - if (!select_printer_from_connect(msg)) { - // If printer was not selected, do not select filament. - return; - } + //if (!select_printer_from_connect(msg)) { + // // If printer was not selected, do not select filament. + // return; + //} + // TODO: Selecting SLA material if (Preset::printer_technology(preset_bundle->printers.get_selected_preset().config) != ptFFF) { return; } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index fb9e84a060..0f2b84a434 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -417,7 +417,8 @@ public: void show_printer_webview_tab(); // return true if preset vas invisible and we have to installed it to make it selectable bool select_printer_preset(const Preset* printer_preset); - bool select_filament_preset(const Preset* filament_preset); + bool select_filament_preset(const Preset* filament_preset, size_t extruder_index); + void search_and_select_filaments(const std::string& material, size_t extruder_index, std::string& out_message); void handle_script_message(std::string msg) {} void request_model_download(std::string import_json) {} void download_project(std::string project_id) {} diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 9378698782..7e2088bb1b 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -165,6 +165,17 @@ namespace { return {}; } + void parse_tree_for_param_vector(const pt::ptree& tree, const std::string& param, std::vector& results) + { + for (const auto& section : tree) { + if (section.first == param) { + results.emplace_back(section.second.data()); + } else { + parse_tree_for_param_vector(section.second, param, results); + } + } + } + pt::ptree parse_tree_for_subtree(const pt::ptree& tree, const std::string& param) { for (const auto& section : tree) { @@ -333,7 +344,7 @@ void UserAccount::fill_compatible_printers_from_json(const std::string& json, st pt::ptree ptree; pt::read_json(ss, ptree); - pt::ptree out = parse_tree_for_subtree(ptree, "printer_type_compatible"); + pt::ptree out = parse_tree_for_subtree(ptree, "supported_printer_models"); if (out.empty()) { BOOST_LOG_TRIVIAL(error) << "Failed to find compatible_printer_type in printer detail."; return; @@ -347,6 +358,80 @@ void UserAccount::fill_compatible_printers_from_json(const std::string& json, st } } +void UserAccount::fill_material_from_json(const std::string& json, std::vector& result) const +{ + + /* option 1: + "slot": { + "active": 2, + "slots": { + "1": { + "material": "PLA", + "temp": 170, + "fan_hotend": 7689, + "fan_print": 0 + }, + "2": { + "material": "PLA", + "temp": 225, + "fan_hotend": 7798, + "fan_print": 6503 + }, + "3": { + "material": "PLA", + "temp": 36, + "fan_hotend": 6636, + "fan_print": 0 + }, + "4": { + "material": "PLA", + "temp": 35, + "fan_hotend": 0, + "fan_print": 0 + }, + "5": { + "material": "PETG", + "temp": 136, + "fan_hotend": 8132, + "fan_print": 0 + } + } + } + */ + /* option 2 + "filament": { + "material": "PLA", + "bed_temperature": 60, + "nozzle_temperature": 210 + } + */ + // try finding "slot" subtree a use it to + // if not found, find "filament" subtree + try { + std::stringstream ss(json); + pt::ptree ptree; + pt::read_json(ss, ptree); + // find "slot" subtree + pt::ptree slot_subtree = parse_tree_for_subtree(ptree, "slot"); + if (slot_subtree.empty()) { + // if not found, find "filament" subtree + pt::ptree filament_subtree = parse_tree_for_subtree(ptree, "filament"); + if (!filament_subtree.empty()) { + std::string material = parse_tree_for_param(filament_subtree, "material"); + if (!material.empty()) { + result.emplace_back(std::move(material)); + } + } + return; + } + // search "slot" subtree for all "material"s + parse_tree_for_param_vector(slot_subtree, "material", result); + } + catch (const std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); + } +} + std::string UserAccount::get_printer_type_from_name(const std::string& printer_name) const { diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index 738e1d773e..d89606701e 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -64,9 +64,9 @@ public: // standalone utility methods std::string get_model_from_json(const std::string& message) const; std::string get_nozzle_from_json(const std::string& message) const; - //std::string get_apikey_from_json(const std::string& message) const; std::string get_keyword_from_json(const std::string& json, const std::string& keyword) const; void fill_compatible_printers_from_json(const std::string& json, std::vector& result) const; + void fill_material_from_json(const std::string& json, std::vector& result) const; const std::map& get_printer_state_table() const { return printer_state_table; }