From 9c6b8edcb1aabbe125374f25237005b6829f2f24 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sat, 24 Jan 2026 15:48:32 +0800 Subject: [PATCH] select machine --- src/slic3r/GUI/GUI_App.cpp | 107 ++++++++++++++++++++++- src/slic3r/GUI/GUI_App.hpp | 3 + src/slic3r/Utils/BBLPrinterAgent.cpp | 3 +- src/slic3r/Utils/NetworkAgentFactory.cpp | 45 ++++++++++ src/slic3r/Utils/NetworkAgentFactory.hpp | 62 +++---------- src/slic3r/Utils/OrcaPrinterAgent.cpp | 3 +- 6 files changed, 169 insertions(+), 54 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 73e09c5556..f891b839f1 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2201,7 +2201,9 @@ void GUI_App::init_networking_callbacks() if (MachineObject* obj = m_device_manager->get_my_machine(dev_id)) { obj->parse_json("lan", msg); - if (this->m_device_manager->get_selected_machine() == obj) { + // Orca: skip it if it doesn't support subscription based filament sync + if (this->m_device_manager->get_selected_machine() == obj && + m_agent->get_filament_sync_mode() == FilamentSyncMode::subscription) { GUI::wxGetApp().sidebar().load_ams_list(obj); } } @@ -3544,9 +3546,112 @@ void GUI_App::switch_printer_agent(const std::string& agent_id) BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": m_device_manager is null, cannot check for deferred connection"; } + // Auto-switch MachineObject + select_machine(effective_agent_id); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": printer agent switched to " << effective_agent_id; } +void GUI_App::select_machine(const std::string& agent_id) +{ + // Skip for BBL agent for now - uses its own device discovery/selection + // Orca todo: revisit in future if we want to support auto-switching for BBL printers + if (agent_id == BBL_PRINTER_AGENT_ID) { + return; + } + + if (!m_device_manager || !preset_bundle) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": no device manager or preset bundle"; + return; + } + + // Get config source (preset or physical printer) + const auto& preset = preset_bundle->printers.get_edited_preset(); + const DynamicPrintConfig* host_cfg = &preset.config; + + std::string print_host = host_cfg->opt_string("print_host"); + if (print_host.empty()) { + if (auto* physical_cfg = preset_bundle->physical_printers.get_selected_printer_config()) { + if (!physical_cfg->opt_string("print_host").empty()) { + host_cfg = physical_cfg; + print_host = host_cfg->opt_string("print_host"); + } + } + } + if (print_host.empty()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": no print_host configured, skipping auto-switch"; + return; + } + + // Normalize host: strip protocol and path + std::string host = print_host; + if (host.find("http://") == 0) host = host.substr(7); + else if (host.find("https://") == 0) host = host.substr(8); + auto slash = host.find('/'); + if (slash != std::string::npos) host = host.substr(0, slash); + // Strip inline port if present (port comes from printhost_port) + auto colon = host.find(':'); + if (colon != std::string::npos) host = host.substr(0, colon); + + // Get port from separate config + std::string port = host_cfg->opt_string("printhost_port"); + + // Build full address (host:port) for dev_ip + std::string full_addr = host; + if (!port.empty()) { + full_addr += ":" + port; + } + + // Generate dev_id (replace . and : with _) + std::string dev_id = full_addr; + std::replace(dev_id.begin(), dev_id.end(), '.', '_'); + std::replace(dev_id.begin(), dev_id.end(), ':', '_'); + + // Check if already exists by dev_id + MachineObject* existing = m_device_manager->get_local_machine(dev_id); + + // If not found by dev_id, search by full_addr + if (!existing) { + auto local_machines = m_device_manager->get_local_machinelist(); + for (auto& [id, machine] : local_machines) { + if (machine && machine->get_dev_ip() == full_addr) { + existing = machine; + dev_id = existing->get_dev_id(); // Use existing dev_id + break; + } + } + } + + // If machine doesn't exist, create it first + if (!existing) { + BBLocalMachine machine; + machine.dev_id = dev_id; + machine.dev_ip = full_addr; + machine.dev_name = agent_id + " (" + full_addr + ")"; + machine.printer_type = preset.config.opt_string("printer_model"); + + existing = m_device_manager->insert_local_device( + machine, "lan", "free", "", ""); + + if (!existing) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": failed to create machine dev_id=" << dev_id; + return; + } + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": created new machine dev_id=" << dev_id; + } + + // Use MonitorPanel::select_machine() to trigger full selection flow + // This reuses existing logic for machine switching (UI updates, callbacks, etc.) + if (mainframe && mainframe->m_monitor) { + mainframe->m_monitor->select_machine(dev_id); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": triggered select_machine for dev_id=" << dev_id; + } else { + // Fallback if MonitorPanel not available + m_device_manager->set_selected_machine(dev_id); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": fallback set_selected_machine dev_id=" << dev_id; + } +} + bool GUI_App::dark_mode() { #ifdef SUPPORT_DARK_MODE diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index e494d0c2bb..6f0c0e028e 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -725,6 +725,9 @@ private: bool config_wizard_startup(); void check_updates(const bool verbose); + // select or add MachineObject + void select_machine(const std::string& agent_id); + bool m_init_app_config_from_older { false }; bool m_datadir_redefined { false }; std::string m_older_data_dir_path; diff --git a/src/slic3r/Utils/BBLPrinterAgent.cpp b/src/slic3r/Utils/BBLPrinterAgent.cpp index a1be053368..e547b424a5 100644 --- a/src/slic3r/Utils/BBLPrinterAgent.cpp +++ b/src/slic3r/Utils/BBLPrinterAgent.cpp @@ -1,5 +1,6 @@ #include "BBLPrinterAgent.hpp" #include "BBLNetworkPlugin.hpp" +#include "NetworkAgentFactory.hpp" #include @@ -208,7 +209,7 @@ int BBLPrinterAgent::set_user_selected_machine(std::string dev_id) AgentInfo BBLPrinterAgent::get_agent_info_static() { return AgentInfo{ - .id = "bbl", + .id = BBL_PRINTER_AGENT_ID, .name = "Bambu Lab Printer Agent", .version = "", .description = "Bambu Lab printer agent" diff --git a/src/slic3r/Utils/NetworkAgentFactory.cpp b/src/slic3r/Utils/NetworkAgentFactory.cpp index fe65f6fc75..0f51d43e62 100644 --- a/src/slic3r/Utils/NetworkAgentFactory.cpp +++ b/src/slic3r/Utils/NetworkAgentFactory.cpp @@ -173,4 +173,49 @@ void NetworkAgentFactory::register_all_agents() BOOST_LOG_TRIVIAL(info) << "Registered " << get_printer_agents().size() << " printer agents"; } +std::unique_ptr create_agent_from_config(const std::string& log_dir, AppConfig* app_config) +{ + // Determine cloud provider from config + bool use_orca_cloud = false; + if (app_config) { + try { + use_orca_cloud = app_config->get("use_orca_cloud") == "true" || app_config->get_bool("use_orca_cloud"); + } catch (...) { + use_orca_cloud = false; + } + } + + // Create cloud agent + CloudAgentProvider provider = use_orca_cloud ? CloudAgentProvider::Orca : CloudAgentProvider::BBL; + auto cloud_agent = NetworkAgentFactory::create_cloud_agent(provider, log_dir); + + // Fall back to Orca if BBL plugin not available + if (!cloud_agent && provider == CloudAgentProvider::BBL) { + BOOST_LOG_TRIVIAL(warning) << "BBL plugin not loaded, falling back to Orca cloud agent"; + cloud_agent = NetworkAgentFactory::create_cloud_agent(CloudAgentProvider::Orca, log_dir); + } + + if (!cloud_agent) { + BOOST_LOG_TRIVIAL(error) << "Failed to create cloud agent"; + return nullptr; + } + + // auto bbl_printer_agent = NetworkAgentFactory::create_printer_agent_by_id("bbl", cloud_agent, log_dir); + + // Create NetworkAgent with cloud agent only (printer agent added later) + // We will create the printer agent later when the printer is selected, so we pass nullptr for the printer agent here. + auto agent = NetworkAgentFactory::create_from_agents(std::move(cloud_agent), nullptr); + + // Configure URL overrides for Orca cloud + if (agent && app_config && use_orca_cloud) { + auto* orca_cloud = dynamic_cast(agent->get_cloud_agent().get()); + if (orca_cloud) { + orca_cloud->configure_urls(app_config); + } + } + + BOOST_LOG_TRIVIAL(info) << "Created NetworkAgent with cloud agent"; + return agent; +} + } // namespace Slic3r diff --git a/src/slic3r/Utils/NetworkAgentFactory.hpp b/src/slic3r/Utils/NetworkAgentFactory.hpp index 121b8dec27..aa7f54dccb 100644 --- a/src/slic3r/Utils/NetworkAgentFactory.hpp +++ b/src/slic3r/Utils/NetworkAgentFactory.hpp @@ -22,12 +22,15 @@ class ICloudServiceAgent; class IPrinterAgent; /** - * AgentProvider - Specifies which implementation to use for each agent type. + * CloudAgentProvider - Specifies which implementation to use for each agent type. * - * - Orca: Native Orca implementations (OrcaCloudServiceAgent, OrcaPrinterAgent) - * - BBL: BBL DLL wrapper implementations (BBLCloudServiceAgent, BBLPrinterAgent) + * - Orca: Native Orca cloud implementations (OrcaCloudServiceAgent) + * - BBL: BBL DLL wrapper implementations (BBLCloudServiceAgent) */ -enum class AgentProvider { Orca, BBL }; +enum class CloudAgentProvider { Orca, BBL }; + +static constexpr char ORCA_PRINTER_AGENT_ID[] = "orca"; +static constexpr char BBL_PRINTER_AGENT_ID[] = "bbl"; // Factory function type for creating printer agents using PrinterAgentFactory = @@ -140,11 +143,11 @@ public: * @param log_dir Directory for log files * @return Shared pointer to ICloudServiceAgent implementation */ - static std::shared_ptr create_cloud_agent(AgentProvider provider, const std::string& log_dir) + static std::shared_ptr create_cloud_agent(CloudAgentProvider provider, const std::string& log_dir) { switch (provider) { - case AgentProvider::Orca: return std::make_shared(log_dir); - case AgentProvider::BBL: { + case CloudAgentProvider::Orca: return std::make_shared(log_dir); + case CloudAgentProvider::BBL: { auto& plugin = BBLNetworkPlugin::instance(); if (!plugin.is_loaded()) { return nullptr; @@ -200,50 +203,7 @@ private: * @param app_config Application configuration object * @return NetworkAgent with cloud agent, or nullptr on failure */ -inline std::unique_ptr create_agent_from_config(const std::string& log_dir, AppConfig* app_config) -{ - // Determine cloud provider from config - bool use_orca_cloud = false; - if (app_config) { - try { - use_orca_cloud = app_config->get("use_orca_cloud") == "true" || app_config->get_bool("use_orca_cloud"); - } catch (...) { - use_orca_cloud = false; - } - } - - // Create cloud agent - AgentProvider provider = use_orca_cloud ? AgentProvider::Orca : AgentProvider::BBL; - auto cloud_agent = NetworkAgentFactory::create_cloud_agent(provider, log_dir); - - // Fall back to Orca if BBL plugin not available - if (!cloud_agent && provider == AgentProvider::BBL) { - BOOST_LOG_TRIVIAL(warning) << "BBL plugin not loaded, falling back to Orca cloud agent"; - cloud_agent = NetworkAgentFactory::create_cloud_agent(AgentProvider::Orca, log_dir); - } - - if (!cloud_agent) { - BOOST_LOG_TRIVIAL(error) << "Failed to create cloud agent"; - return nullptr; - } - - // auto bbl_printer_agent = NetworkAgentFactory::create_printer_agent_by_id("bbl", cloud_agent, log_dir); - - // Create NetworkAgent with cloud agent only (printer agent added later) - // We will create the printer agent later when the printer is selected, so we pass nullptr for the printer agent here. - auto agent = NetworkAgentFactory::create_from_agents(std::move(cloud_agent), nullptr); - - // Configure URL overrides for Orca cloud - if (agent && app_config && use_orca_cloud) { - auto* orca_cloud = dynamic_cast(agent->get_cloud_agent().get()); - if (orca_cloud) { - orca_cloud->configure_urls(app_config); - } - } - - BOOST_LOG_TRIVIAL(info) << "Created NetworkAgent with cloud agent"; - return agent; -} +std::unique_ptr create_agent_from_config(const std::string& log_dir, AppConfig* app_config); } // namespace Slic3r diff --git a/src/slic3r/Utils/OrcaPrinterAgent.cpp b/src/slic3r/Utils/OrcaPrinterAgent.cpp index 1002e4068d..09acf3465d 100644 --- a/src/slic3r/Utils/OrcaPrinterAgent.cpp +++ b/src/slic3r/Utils/OrcaPrinterAgent.cpp @@ -1,4 +1,5 @@ #include "OrcaPrinterAgent.hpp" +#include "NetworkAgentFactory.hpp" #include @@ -139,7 +140,7 @@ int OrcaPrinterAgent::set_user_selected_machine(std::string dev_id) // ============================================================================ AgentInfo OrcaPrinterAgent::get_agent_info_static() { - return AgentInfo{.id = "orca", + return AgentInfo{.id = ORCA_PRINTER_AGENT_ID, .name = "Orca Printer Agent", .version = OrcaPrinterAgent_VERSION, .description = "Orca Printer Communication Protocol Agent"};