From 042e6bf9914ba12a078bd793a28c98d564b26175 Mon Sep 17 00:00:00 2001 From: "chunmao.guo" Date: Wed, 16 Aug 2023 15:38:16 +0800 Subject: [PATCH] ENH: [STUDIO-4029] sync printer config with cloud Change-Id: Icffee9d5987131e1d78d51ccfcafeefff18f26cb Jira: STUDIO-4029 (cherry picked from commit 5b58e5f2658753efbf11037f0b6cbb023070c0ea) --- src/slic3r/GUI/DeviceManager.cpp | 18 ++- src/slic3r/GUI/DeviceManager.hpp | 2 + src/slic3r/GUI/NotificationManager.cpp | 1 + src/slic3r/GUI/NotificationManager.hpp | 12 ++ src/slic3r/GUI/Plater.cpp | 3 + src/slic3r/Utils/PresetUpdater.cpp | 145 ++++++++++++++++++++++++- src/slic3r/Utils/PresetUpdater.hpp | 1 + src/slic3r/Utils/json_diff.cpp | 19 ++-- 8 files changed, 186 insertions(+), 15 deletions(-) diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index d03c6dc29..d29fea57b 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -470,6 +470,12 @@ PrinterArch MachineObject::get_printer_arch() const return DeviceManager::get_printer_arch(printer_type); } +void MachineObject::reload_printer_settings() +{ + print_json.load_compatible_settings("", ""); + parse_json("{}"); +} + MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string id, std::string ip) :dev_name(name), dev_id(id), @@ -2592,10 +2598,8 @@ int MachineObject::parse_json(std::string payload) if (j_pre["print"]["msg"].get() == 0) { //all message BOOST_LOG_TRIVIAL(trace) << "static: get push_all msg, dev_id=" << dev_id; m_push_count++; - if (j_pre["print"].contains("printer_type")) { - printer_type = parse_printer_type(j_pre["print"]["printer_type"].get()); - } - print_json.load_compatible_settings(printer_type, ""); + if (!printer_type.empty()) + print_json.load_compatible_settings(printer_type, ""); print_json.diff2all_base_reset(j_pre); } else if (j_pre["print"]["msg"].get() == 1) { //diff message if (print_json.diff2all(j_pre, j) == 0) { @@ -4764,6 +4768,12 @@ MachineObject* DeviceManager::get_local_selected_machine() return get_local_machine(local_selected_machine); } +void DeviceManager::reload_printer_settings() +{ + for (auto obj : this->userMachineList) + obj.second->reload_printer_settings(); +} + MachineObject* DeviceManager::get_default_machine() { std::string dev_id; diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index fb183feb3..6bd2eaa06 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -413,6 +413,7 @@ public: std::string printer_type; /* model_id */ PrinterSeries get_printer_series() const; PrinterArch get_printer_arch() const; + void reload_printer_settings(); std::string printer_thumbnail_img; std::string monitor_upgrade_printer_img; @@ -911,6 +912,7 @@ public: MachineObject* get_my_machine(std::string dev_id); void erase_user_machine(std::string dev_id); void clean_user_info(); + void reload_printer_settings(); bool set_selected_machine(std::string dev_id, bool need_disconnect = false); MachineObject* get_selected_machine(); diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 4a03b572f..facc99ad3 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -39,6 +39,7 @@ namespace GUI { wxDEFINE_EVENT(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, EjectDriveNotificationClickedEvent); wxDEFINE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent); wxDEFINE_EVENT(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, PresetUpdateAvailableClickedEvent); +wxDEFINE_EVENT(EVT_PRINTER_CONFIG_UPDATE_AVAILABLE_CLICKED, PrinterConfigUpdateAvailableClickedEvent); namespace { /* // not used? diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 7127ce30e..0a0519b96 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -27,6 +27,8 @@ using ExportGcodeNotificationClickedEvent = SimpleEvent; wxDECLARE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent); using PresetUpdateAvailableClickedEvent = SimpleEvent; wxDECLARE_EVENT(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, PresetUpdateAvailableClickedEvent); +using PrinterConfigUpdateAvailableClickedEvent = SimpleEvent; +wxDECLARE_EVENT(EVT_PRINTER_CONFIG_UPDATE_AVAILABLE_CLICKED, PrinterConfigUpdateAvailableClickedEvent); using CancelFn = std::function; @@ -141,6 +143,7 @@ enum class NotificationType BBLPluginInstallHint, BBLPluginUpdateAvailable, BBLPreviewOnlyMode, + BBLPrinterConfigUpdateAvailable, }; class NotificationManager @@ -914,6 +917,15 @@ private: return true; }}, + NotificationData{NotificationType::BBLPrinterConfigUpdateAvailable, NotificationLevel::ImportantNotificationLevel, BBL_NOTICE_MAX_INTERVAL, + _u8L("New printer config available."), + _u8L("Details"), + [](wxEvtHandler* evnthndlr) { + if (evnthndlr != nullptr) + wxPostEvent(evnthndlr, PrinterConfigUpdateAvailableClickedEvent(EVT_PRINTER_CONFIG_UPDATE_AVAILABLE_CLICKED)); + return true; + }}, + NotificationData{NotificationType::UndoDesktopIntegrationFail, NotificationLevel::WarningNotificationLevel, 10, _u8L("Undo integration failed.") }, NotificationData{NotificationType::ExportOngoing, NotificationLevel::RegularNotificationLevel, 0, _u8L("Exporting.")}, diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 538783035..f03814d58 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2693,6 +2693,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->q->Bind(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, [this](EjectDriveNotificationClickedEvent&) { this->q->eject_drive(); }); this->q->Bind(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, [this](ExportGcodeNotificationClickedEvent&) { this->q->export_gcode(true); }); this->q->Bind(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, [](PresetUpdateAvailableClickedEvent&) { wxGetApp().get_preset_updater()->on_update_notification_confirm(); }); + this->q->Bind(EVT_PRINTER_CONFIG_UPDATE_AVAILABLE_CLICKED, [](PrinterConfigUpdateAvailableClickedEvent&) { + wxGetApp().get_preset_updater()->do_printer_config_update(); + wxGetApp().getDeviceManager()->reload_printer_settings(); }); /* BBS do not handle removeable driver event */ this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this](RemovableDriveEjectEvent &evt) { diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index acc0ec4f7..a2b982393 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -212,6 +212,8 @@ struct PresetUpdater::priv bool has_waiting_updates { false }; Updates waiting_updates; + bool has_waiting_printer_updates { false }; + Updates waiting_printer_updates; struct Resource { @@ -235,11 +237,13 @@ struct PresetUpdater::priv void sync_config(std::string http_url, const VendorMap vendors); void sync_tooltip(std::string http_url, std::string language); void sync_plugins(std::string http_url, std::string plugin_version); - bool get_cached_plugins_version(std::string& cached_version); + void sync_printer_config(std::string http_url); + bool get_cached_plugins_version(std::string &cached_version); //BBS: refine preset update logic bool install_bundles_rsrc(std::vector bundles, bool snapshot) const; void check_installed_vendor_profiles() const; + Updates get_printer_config_updates(bool update = false) const; Updates get_config_updates(const Semver& old_slic3r_version) const; bool perform_updates(Updates &&updates, bool snapshot = true) const; void set_waiting_updates(Updates u); @@ -257,6 +261,7 @@ PresetUpdater::priv::priv() set_download_prefs(GUI::wxGetApp().app_config); // Install indicies from resources. Only installs those that are either missing or older than in resources. check_installed_vendor_profiles(); + perform_updates(get_printer_config_updates(), false); // Load indices from the cache directory. //index_db = Index::load_db(); } @@ -869,7 +874,7 @@ void PresetUpdater::priv::sync_tooltip(std::string http_url, std::string languag } } -//return true means there are plugins files +// return true means there are plugins files bool PresetUpdater::priv::get_cached_plugins_version(std::string& cached_version) { std::string data_dir_str = data_dir(); @@ -1013,6 +1018,68 @@ void PresetUpdater::priv::sync_plugins(std::string http_url, std::string plugin_ } } +void PresetUpdater::priv::sync_printer_config(std::string http_url) +{ + std::string curr_version = SLIC3R_VERSION; + std::string using_version = curr_version.substr(0, 6) + "00.00"; + + std::string cached_version; + std::string data_dir_str = data_dir(); + boost::filesystem::path data_dir_path(data_dir_str); + auto config_folder = data_dir_path / "printers"; + auto cache_folder = data_dir_path / "ota" / "printers"; + + try { + boost::filesystem::load_string_file(config_folder / "version.txt", curr_version); + boost::algorithm::trim(curr_version); + } catch (...) {} + try { + boost::filesystem::load_string_file(cache_folder / "version.txt", cached_version); + boost::algorithm::trim(cached_version); + } catch (...) {} + if (!cached_version.empty()) { + bool need_delete_cache = false; + Semver current_semver = curr_version; + Semver cached_semver = cached_version; + + if ((cached_semver.maj() != current_semver.maj()) || (cached_semver.min() != current_semver.min())) { + need_delete_cache = true; + BOOST_LOG_TRIVIAL(info) << boost::format("cached printer config version %1% not match with current %2%") % cached_version % curr_version; + } else if (cached_semver.patch() <= current_semver.patch()) { + need_delete_cache = true; + BOOST_LOG_TRIVIAL(info) << boost::format("cached printer config version %1% not newer than current %2%") % cached_version % curr_version; + } else { + using_version = cached_version; + } + + if (need_delete_cache) { + std::string data_dir_str = data_dir(); + cached_version = curr_version; + } + } + + try { + std::map resources{{"slicer/printer/bbl", {using_version, "", "", cache_folder.string()}}}; + sync_resources(http_url, resources, false, cached_version, "printer.json"); + } catch (std::exception &e) { + BOOST_LOG_TRIVIAL(warning) << format("[BBL Updater] sync_printer_config: %1%", e.what()); + } + + bool result = false; + try { + boost::filesystem::load_string_file(cache_folder / "version.txt", cached_version); + boost::algorithm::trim(cached_version); + result = true; + } catch (...) {} + if (result) { + BOOST_LOG_TRIVIAL(info) << format("[BBL Updater] found new printer config: %1%, prompt to update", cached_version); + waiting_printer_updates = get_printer_config_updates(true); + if (waiting_printer_updates.updates.size() > 0) { + has_waiting_printer_updates = true; + GUI::wxGetApp().plater()->get_notification_manager()->push_notification(GUI::NotificationType::BBLPrinterConfigUpdateAvailable); + } + } +} bool PresetUpdater::priv::install_bundles_rsrc(std::vector bundles, bool snapshot) const { @@ -1109,6 +1176,53 @@ void PresetUpdater::priv::check_installed_vendor_profiles() const install_bundles_rsrc(bundles, false); } +Updates PresetUpdater::priv::get_printer_config_updates(bool update) const +{ + std::string data_dir_str = data_dir(); + boost::filesystem::path data_dir_path(data_dir_str); + boost::filesystem::path resc_dir_path(resources_dir()); + auto config_folder = data_dir_path / "printers"; + auto resc_folder = (update ? cache_path : resc_dir_path) / "printers"; + std::string curr_version; + std::string resc_version; + try { + boost::filesystem::load_string_file(resc_folder / "version.txt", resc_version); + boost::algorithm::trim(resc_version); + } catch (...) {} + try { + boost::filesystem::load_string_file(config_folder / "version.txt", curr_version); + boost::algorithm::trim(curr_version); + } catch (...) {} + + if (!curr_version.empty()) { + Semver curr_ver = curr_version; + Semver resc_ver = resc_version; + + bool version_match = ((resc_ver.maj() == curr_ver.maj()) && (resc_ver.min() == curr_ver.min())); + + if (!version_match || (curr_ver < resc_ver)) { + BOOST_LOG_TRIVIAL(info) << "[BBL Updater]:found newer version " << resc_version << " from resource, old version " << curr_version; + } else { + return {}; + } + } + Updates updates; + Version version; + version.config_version = resc_version; + std::string change_log; + if (update) { + std::string changelog_file = (resc_folder / "printer.json").string(); + try { + boost::nowide::ifstream ifs(changelog_file); + json j; + ifs >> j; + version.comment = j["description"]; + } catch (...) {} + } + updates.updates.emplace_back(std::move(resc_folder), std::move(config_folder), version, "bbl", change_log, version.comment, false, true); + return updates; +} + // Generates a list of bundle updates that are to be performed. // Version of slic3r that was running the last time and which was read out from PrusaSlicer.ini is provided // as a parameter. @@ -1303,7 +1417,8 @@ void PresetUpdater::sync(std::string http_url, std::string language, std::string } if (p->cancel) return; - this->p->sync_plugins(http_url, plugin_version); + this->p->sync_plugins(http_url, plugin_version); + this->p->sync_printer_config(http_url); //if (p->cancel) // return; //remove the tooltip currently @@ -1492,6 +1607,30 @@ void PresetUpdater::on_update_notification_confirm() } } +void PresetUpdater::do_printer_config_update() +{ + if (!p->has_waiting_printer_updates) + return; + BOOST_LOG_TRIVIAL(info) << "Update of printer configs available. Asking for confirmation ..."; + + std::vector updates_msg; + for (const auto &update : p->waiting_printer_updates.updates) { + std::string changelog = update.change_log; + updates_msg.emplace_back(update.vendor, update.version.config_version, update.descriptions, std::move(changelog)); + } + + GUI::MsgUpdateConfig dlg(updates_msg); + + const auto res = dlg.ShowModal(); + if (res == wxID_OK) { + BOOST_LOG_TRIVIAL(debug) << "User agreed to perform the update"; + if (p->perform_updates(std::move(p->waiting_printer_updates))) + p->has_waiting_printer_updates = false; + } else { + BOOST_LOG_TRIVIAL(info) << "User refused the update"; + } +} + bool PresetUpdater::version_check_enabled() const { return p->enabled_version_check; diff --git a/src/slic3r/Utils/PresetUpdater.hpp b/src/slic3r/Utils/PresetUpdater.hpp index 306c0549f..6d6e4cd94 100644 --- a/src/slic3r/Utils/PresetUpdater.hpp +++ b/src/slic3r/Utils/PresetUpdater.hpp @@ -57,6 +57,7 @@ public: bool install_bundles_rsrc(std::vector bundles, bool snapshot = true) const; void on_update_notification_confirm(); + void do_printer_config_update(); bool version_check_enabled() const; diff --git a/src/slic3r/Utils/json_diff.cpp b/src/slic3r/Utils/json_diff.cpp index a4f4bbcce..d82ef2134 100644 --- a/src/slic3r/Utils/json_diff.cpp +++ b/src/slic3r/Utils/json_diff.cpp @@ -75,21 +75,24 @@ int json_diff::all2diff_base_reset(json const &base) bool json_diff::load_compatible_settings(std::string const &type, std::string const &version) { - std::string type2 = type.empty() ? printer_type : type; - std::string version2 = version.empty() ? printer_version : version; - if (type2 == printer_type && version2 == printer_version) - return false; - printer_type = type2; - printer_version = version2; + // Reload on empty type and version + if (!type.empty() || !version.empty()) { + std::string type2 = type.empty() ? printer_type : type; + std::string version2 = version.empty() ? printer_version : version; + if (type2 == printer_type && version2 == printer_version) + return false; + printer_type = type2; + printer_version = version2; + } settings_base.clear(); - std::string config_file = Slic3r::resources_dir() + "/printers/" + type2 + ".json"; + std::string config_file = Slic3r::data_dir() + "/printers/" + printer_type + ".json"; boost::nowide::ifstream json_file(config_file.c_str()); try { json versions; if (json_file.is_open()) { json_file >> versions; for (auto iter = versions.begin(); iter != versions.end(); ++iter) { - if (iter.key() > version2) + if (iter.key() > printer_version) break; merge_objects(*iter, settings_base); }