init
This commit is contained in:
@@ -300,6 +300,13 @@ void AppConfig::set_defaults()
|
||||
if (get("allow_abnormal_storage").empty()) {
|
||||
set_bool("allow_abnormal_storage", false);
|
||||
}
|
||||
#ifdef __linux__
|
||||
if (get(SETTING_USE_ENCRYPTED_TOKEN_FILE).empty())
|
||||
set_bool(SETTING_USE_ENCRYPTED_TOKEN_FILE, true);
|
||||
#else
|
||||
if (get(SETTING_USE_ENCRYPTED_TOKEN_FILE).empty())
|
||||
set_bool(SETTING_USE_ENCRYPTED_TOKEN_FILE, false);
|
||||
#endif
|
||||
|
||||
if(get("check_stable_update_only").empty()) {
|
||||
set_bool("check_stable_update_only", false);
|
||||
|
||||
@@ -28,6 +28,7 @@ using namespace nlohmann;
|
||||
#define SETTING_NETWORK_PLUGIN_SKIPPED_VERSIONS "network_plugin_skipped_versions"
|
||||
#define SETTING_NETWORK_PLUGIN_UPDATE_DISABLED "network_plugin_update_prompts_disabled"
|
||||
#define SETTING_NETWORK_PLUGIN_REMIND_LATER "network_plugin_remind_later"
|
||||
#define SETTING_USE_ENCRYPTED_TOKEN_FILE "use_encrypted_token_file"
|
||||
#define BAMBU_NETWORK_AGENT_VERSION_LEGACY "01.10.01.01"
|
||||
|
||||
#define SUPPORT_DARK_MODE
|
||||
|
||||
@@ -1017,7 +1017,7 @@ static std::vector<std::string> s_Preset_printer_options {
|
||||
"scan_first_layer", "enable_power_loss_recovery", "wrapping_detection_layers", "wrapping_exclude_area", "machine_load_filament_time", "machine_unload_filament_time", "machine_tool_change_time", "time_cost", "machine_pause_gcode", "template_custom_gcode",
|
||||
"nozzle_type", "nozzle_hrc","auxiliary_fan", "nozzle_volume","upward_compatible_machine", "z_hop_types", "travel_slope", "retract_lift_enforce","support_chamber_temp_control","support_air_filtration","printer_structure",
|
||||
"best_object_pos", "head_wrap_detect_zone",
|
||||
"host_type", "print_host", "printhost_apikey", "bbl_use_printhost",
|
||||
"host_type", "print_host", "printhost_apikey", "bbl_use_printhost", "printer_agent",
|
||||
"print_host_webui",
|
||||
"printhost_cafile","printhost_port","printhost_authorization_type",
|
||||
"printhost_user", "printhost_password", "printhost_ssl_ignore_revoke", "thumbnails", "thumbnails_format",
|
||||
@@ -1502,7 +1502,7 @@ int PresetCollection::get_differed_values_to_update(Preset& preset, std::map<std
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " uploading user preset name is: " << preset.name << "and create filament_id is: " << preset.filament_id
|
||||
<< " and base_id is: " << preset.base_id;
|
||||
key_values[BBL_JSON_KEY_UPDATE_TIME] = std::to_string(preset.updated_time);
|
||||
key_values[ORCA_JSON_KEY_UPDATE_TIME] = std::to_string(preset.updated_time);
|
||||
key_values[BBL_JSON_KEY_TYPE] = Preset::get_iot_type_string(preset.type);
|
||||
return 0;
|
||||
}
|
||||
@@ -1802,8 +1802,8 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
|
||||
|
||||
//update_time
|
||||
long long cloud_update_time = 0;
|
||||
if (preset_values.find(BBL_JSON_KEY_UPDATE_TIME) != preset_values.end()) {
|
||||
cloud_update_time = std::atoll(preset_values[BBL_JSON_KEY_UPDATE_TIME].c_str());
|
||||
if (preset_values.find(ORCA_JSON_KEY_UPDATE_TIME) != preset_values.end()) {
|
||||
cloud_update_time = std::atoll(preset_values[ORCA_JSON_KEY_UPDATE_TIME].c_str());
|
||||
}
|
||||
|
||||
//user_id
|
||||
@@ -3395,6 +3395,7 @@ static std::vector<std::string> s_PhysicalPrinter_opts {
|
||||
"printer_technology",
|
||||
"bbl_use_printhost",
|
||||
"host_type",
|
||||
"printer_agent",
|
||||
"print_host",
|
||||
"print_host_webui",
|
||||
"printhost_apikey",
|
||||
|
||||
@@ -52,7 +52,8 @@
|
||||
#define BBL_JSON_KEY_BASE_ID "base_id"
|
||||
#define BBL_JSON_KEY_USER_ID "user_id"
|
||||
#define BBL_JSON_KEY_FILAMENT_ID "filament_id"
|
||||
#define BBL_JSON_KEY_UPDATE_TIME "updated_time"
|
||||
#define ORCA_JSON_KEY_UPDATE_TIME "updated_time"
|
||||
#define ORCA_JSON_KEY_CREATED_TIME "created_time"
|
||||
#define BBL_JSON_KEY_INHERITS "inherits"
|
||||
#define BBL_JSON_KEY_INSTANTIATION "instantiation"
|
||||
#define BBL_JSON_KEY_NOZZLE_DIAMETER "nozzle_diameter"
|
||||
|
||||
@@ -740,6 +740,13 @@ void PrintConfigDef::init_common_params()
|
||||
def->cli = ConfigOptionDef::nocli;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("printer_agent", coString);
|
||||
def->label = L("Printer Agent");
|
||||
def->tooltip = L("Select the network agent implementation for printer communication.");
|
||||
def->mode = comAdvanced;
|
||||
def->cli = ConfigOptionDef::nocli;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("print_host", coString);
|
||||
def->label = L("Hostname, IP or URL");
|
||||
def->tooltip = L("Orca Slicer can upload G-code files to a printer host. This field should contain "
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <cassert>
|
||||
#include <ctime>
|
||||
#include <cstdio>
|
||||
#include <cctype>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <map>
|
||||
@@ -230,5 +231,76 @@ time_t str2time(const std::string &str, TimeZone zone, TimeFormat fmt)
|
||||
return str2time(ss, zone, fmtstr.c_str());
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// Millisecond timestamps for cloud sync protocol
|
||||
|
||||
std::string millis_to_iso8601(long long unix_millis)
|
||||
{
|
||||
time_t seconds = static_cast<time_t>(unix_millis / 1000);
|
||||
int millis = static_cast<int>(unix_millis % 1000);
|
||||
|
||||
std::tm tms = {};
|
||||
_gmtime_r(&seconds, &tms);
|
||||
|
||||
char buf[32];
|
||||
std::snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
|
||||
tms.tm_year + 1900,
|
||||
tms.tm_mon + 1,
|
||||
tms.tm_mday,
|
||||
tms.tm_hour,
|
||||
tms.tm_min,
|
||||
tms.tm_sec,
|
||||
millis);
|
||||
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
long long iso8601_to_millis(const std::string& iso_time)
|
||||
{
|
||||
if (iso_time.empty()) return -1;
|
||||
|
||||
int y, M, d, h, m, s, ms = 0;
|
||||
|
||||
// Try parsing with milliseconds: "2025-11-28T14:30:00.123Z"
|
||||
int parsed = sscanf(iso_time.c_str(), "%d-%d-%dT%d:%d:%d.%dZ",
|
||||
&y, &M, &d, &h, &m, &s, &ms);
|
||||
|
||||
if (parsed < 6) {
|
||||
// Try without milliseconds: "2025-11-28T14:30:00Z"
|
||||
parsed = sscanf(iso_time.c_str(), "%d-%d-%dT%d:%d:%dZ",
|
||||
&y, &M, &d, &h, &m, &s);
|
||||
ms = 0;
|
||||
}
|
||||
|
||||
if (parsed < 6) return -1;
|
||||
|
||||
// Normalize milliseconds (handle .1, .12, .123, .1234, etc.)
|
||||
if (parsed >= 7) {
|
||||
// Count digits in the fractional part to normalize
|
||||
const char* dot = strchr(iso_time.c_str(), '.');
|
||||
if (dot) {
|
||||
int digits = 0;
|
||||
for (const char* p = dot + 1; *p && *p != 'Z' && std::isdigit(*p); ++p)
|
||||
digits++;
|
||||
// Normalize to 3 digits (milliseconds)
|
||||
while (digits < 3) { ms *= 10; digits++; }
|
||||
while (digits > 3) { ms /= 10; digits--; }
|
||||
}
|
||||
}
|
||||
|
||||
std::tm tms = {};
|
||||
tms.tm_year = y - 1900;
|
||||
tms.tm_mon = M - 1;
|
||||
tms.tm_mday = d;
|
||||
tms.tm_hour = h;
|
||||
tms.tm_min = m;
|
||||
tms.tm_sec = s;
|
||||
|
||||
time_t seconds = _timegm(&tms);
|
||||
if (seconds == time_t(-1)) return -1;
|
||||
|
||||
return static_cast<long long>(seconds) * 1000 + ms;
|
||||
}
|
||||
|
||||
}; // namespace Utils
|
||||
}; // namespace Slic3r
|
||||
|
||||
@@ -63,6 +63,15 @@ inline time_t parse_iso_utc_timestamp(const std::string &str)
|
||||
return str2time(str, TimeZone::utc, TimeFormat::iso8601Z);
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// Millisecond timestamps for cloud sync protocol
|
||||
// Format: "2025-11-28T14:30:00.123Z" (ISO 8601 with milliseconds)
|
||||
|
||||
// Lossless conversion: Unix milliseconds <-> ISO 8601
|
||||
// Format: "YYYY-MM-DDTHH:MM:SS.sssZ" (always 3 decimal places for milliseconds)
|
||||
std::string millis_to_iso8601(long long unix_millis);
|
||||
long long iso8601_to_millis(const std::string& iso_time); // Returns -1 on parse error
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
@@ -598,6 +598,24 @@ set(SLIC3R_GUI_SOURCES
|
||||
Utils/MKS.hpp
|
||||
Utils/NetworkAgent.cpp
|
||||
Utils/NetworkAgent.hpp
|
||||
Utils/NetworkAgentFactory.hpp
|
||||
Utils/NetworkAgentFactory.cpp
|
||||
Utils/ICloudServiceAgent.hpp
|
||||
Utils/IPrinterAgent.hpp
|
||||
Utils/OrcaCloudServiceAgent.cpp
|
||||
Utils/OrcaCloudServiceAgent.hpp
|
||||
Utils/OrcaPrinterAgent.cpp
|
||||
Utils/OrcaPrinterAgent.hpp
|
||||
Utils/QidiPrinterAgent.cpp
|
||||
Utils/QidiPrinterAgent.hpp
|
||||
Utils/MoonrakerPrinterAgent.cpp
|
||||
Utils/MoonrakerPrinterAgent.hpp
|
||||
Utils/BBLCloudServiceAgent.cpp
|
||||
Utils/BBLCloudServiceAgent.hpp
|
||||
Utils/BBLPrinterAgent.cpp
|
||||
Utils/BBLPrinterAgent.hpp
|
||||
Utils/BBLNetworkPlugin.cpp
|
||||
Utils/BBLNetworkPlugin.hpp
|
||||
Utils/Obico.cpp
|
||||
Utils/Obico.hpp
|
||||
Utils/OctoPrint.cpp
|
||||
|
||||
@@ -869,7 +869,7 @@ void BindMachineDialog::on_show(wxShowEvent &event)
|
||||
m_printer_name->SetLabelText(from_u8(m_machine_info->get_dev_name()));
|
||||
|
||||
if (wxGetApp().is_user_login()) {
|
||||
wxString username_text = from_u8(wxGetApp().getAgent()->get_user_nickanme());
|
||||
wxString username_text = from_u8(wxGetApp().getAgent()->get_user_nickname());
|
||||
m_user_name->SetLabelText(username_text);
|
||||
|
||||
std::string avatar_url = wxGetApp().getAgent()->get_user_avatar();
|
||||
|
||||
@@ -255,6 +255,8 @@ public:
|
||||
long tray_read_done_bits = 0;
|
||||
long tray_reading_bits = 0;
|
||||
bool ams_air_print_status { false };
|
||||
/** Whether this printer supports virtual trays (external/manual filament loading).
|
||||
* When true, vt_slot data is used by build_filament_ams_list() to include external filaments. */
|
||||
bool ams_support_virtual_tray { true };
|
||||
time_t ams_user_setting_start = 0;
|
||||
time_t ams_switch_filament_start = 0;
|
||||
@@ -856,7 +858,16 @@ public:
|
||||
bool is_enable_np{ false };
|
||||
bool is_enable_ams_np{ false };
|
||||
|
||||
/*vi slot data*/
|
||||
/**
|
||||
* Virtual Tray (vt_slot) - External/manual filament loading slots.
|
||||
*
|
||||
* Data Flow: Populated from printer JSON via parse_vt_tray() during MachineObject::parse_json().
|
||||
* Used by: Sidebar::build_filament_ams_list() when ams_support_virtual_tray is true.
|
||||
*
|
||||
* Virtual trays represent filament that is manually loaded into the extruder
|
||||
* rather than fed through an AMS unit. This supports printers without AMS
|
||||
* or scenarios where users want to bypass the AMS.
|
||||
*/
|
||||
std::vector<DevAmsTray> vt_slot;
|
||||
DevAmsTray parse_vt_tray(json vtray);
|
||||
|
||||
|
||||
@@ -119,6 +119,10 @@
|
||||
#include "ModelMall.hpp"
|
||||
#include "HintNotification.hpp"
|
||||
|
||||
#include "slic3r/Utils/NetworkAgentFactory.hpp"
|
||||
#include "slic3r/Utils/BBLNetworkPlugin.hpp"
|
||||
#include "slic3r/Utils/bambu_networking.hpp"
|
||||
|
||||
//#ifdef WIN32
|
||||
//#include "BaseException.h"
|
||||
//#endif
|
||||
@@ -1176,9 +1180,9 @@ std::string GUI_App::get_plugin_url(std::string name, std::string country_code)
|
||||
curr_version = BAMBU_NETWORK_AGENT_VERSION_LEGACY;
|
||||
} else if (name == "plugins" && app_config) {
|
||||
std::string user_version = app_config->get_network_plugin_version();
|
||||
curr_version = user_version.empty() ? BBL::get_latest_network_version() : user_version;
|
||||
curr_version = user_version.empty() ? get_latest_network_version() : user_version;
|
||||
} else {
|
||||
curr_version = BBL::get_latest_network_version();
|
||||
curr_version = get_latest_network_version();
|
||||
}
|
||||
|
||||
std::string using_version = curr_version.substr(0, 9) + "00";
|
||||
@@ -1519,7 +1523,7 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP
|
||||
if (name == "plugins") {
|
||||
std::string config_version = app_config->get_network_plugin_version();
|
||||
if (config_version.empty()) {
|
||||
config_version = BBL::get_latest_network_version();
|
||||
config_version = get_latest_network_version();
|
||||
BOOST_LOG_TRIVIAL(info) << "[install_plugin] config_version was empty, using latest: " << config_version;
|
||||
app_config->set_network_plugin_version(config_version);
|
||||
GUI::wxGetApp().CallAfter([this] {
|
||||
@@ -1814,7 +1818,7 @@ bool GUI_App::hot_reload_network_plugin()
|
||||
|
||||
std::string GUI_App::get_latest_network_version() const
|
||||
{
|
||||
return BBL::get_latest_network_version();
|
||||
return Slic3r::get_latest_network_version();
|
||||
}
|
||||
|
||||
bool GUI_App::has_network_update_available() const
|
||||
@@ -1919,9 +1923,9 @@ bool GUI_App::check_networking_version()
|
||||
studio_ver = BAMBU_NETWORK_AGENT_VERSION_LEGACY;
|
||||
} else if (app_config) {
|
||||
std::string user_version = app_config->get_network_plugin_version();
|
||||
studio_ver = user_version.empty() ? BBL::get_latest_network_version() : user_version;
|
||||
studio_ver = user_version.empty() ? get_latest_network_version() : user_version;
|
||||
} else {
|
||||
studio_ver = BBL::get_latest_network_version();
|
||||
studio_ver = get_latest_network_version();
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "check_networking_version: network_ver=" << network_ver << ", expected=" << studio_ver;
|
||||
@@ -2233,6 +2237,8 @@ GUI_App::~GUI_App()
|
||||
}
|
||||
|
||||
StaticBambuLib::release();
|
||||
BBLNetworkPlugin::shutdown();
|
||||
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": exit");
|
||||
}
|
||||
@@ -3323,7 +3329,7 @@ __retry:
|
||||
std::string loaded_version = Slic3r::NetworkAgent::get_version();
|
||||
if (app_config && !loaded_version.empty() && loaded_version != "00.00.00.00") {
|
||||
std::string config_version = app_config->get_network_plugin_version();
|
||||
std::string config_base = BBL::extract_base_version(config_version);
|
||||
std::string config_base = extract_base_version(config_version);
|
||||
if (config_base != loaded_version) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": syncing config version from " << config_version << " to loaded " << loaded_version;
|
||||
app_config->set(SETTING_NETWORK_PLUGIN_VERSION, loaded_version);
|
||||
@@ -3370,7 +3376,12 @@ __retry:
|
||||
//std::string data_dir = wxStandardPaths::Get().GetUserDataDir().ToUTF8().data();
|
||||
std::string data_directory = data_dir();
|
||||
|
||||
m_agent = new Slic3r::NetworkAgent(data_directory);
|
||||
// Register all printer agents before creating the network agent
|
||||
Slic3r::NetworkAgentFactory::register_all_agents();
|
||||
|
||||
// m_agent = new Slic3r::NetworkAgent(data_directory);
|
||||
std::unique_ptr<Slic3r::NetworkAgent> agent_ptr = Slic3r::create_agent_from_config(data_directory, app_config);
|
||||
m_agent = agent_ptr.release();
|
||||
|
||||
if (!m_device_manager)
|
||||
m_device_manager = new Slic3r::DeviceManager(m_agent);
|
||||
@@ -3460,6 +3471,82 @@ unsigned GUI_App::get_colour_approx_luma(const wxColour &colour)
|
||||
));
|
||||
}
|
||||
|
||||
void GUI_App::switch_printer_agent(const std::string& agent_id)
|
||||
{
|
||||
if (!m_agent) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": no agent exists";
|
||||
return;
|
||||
}
|
||||
|
||||
// Use registry to validate and create agent
|
||||
// If empty, use default
|
||||
std::string effective_agent_id = agent_id.empty() ? NetworkAgentFactory::get_default_printer_agent_id() : agent_id;
|
||||
|
||||
// Check if agent is registered
|
||||
if (!NetworkAgentFactory::is_printer_agent_registered(effective_agent_id)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": unregistered agent ID '" << effective_agent_id
|
||||
<< "', keeping current agent";
|
||||
// Keep current agent, don't switch
|
||||
return;
|
||||
}
|
||||
|
||||
std::string current_agent_id;
|
||||
if (m_agent && m_agent->get_printer_agent())
|
||||
current_agent_id = m_agent->get_printer_agent()->get_agent_info().id;
|
||||
|
||||
if (!current_agent_id.empty() && current_agent_id == effective_agent_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string log_dir = data_dir();
|
||||
std::shared_ptr<ICloudServiceAgent> cloud_agent = m_agent->get_cloud_agent();
|
||||
if (!cloud_agent) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": no cloud agent available";
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new printer agent via registry
|
||||
std::shared_ptr<IPrinterAgent> new_printer_agent =
|
||||
NetworkAgentFactory::create_printer_agent_by_id(effective_agent_id, cloud_agent, log_dir);
|
||||
|
||||
if (!new_printer_agent) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": failed to create agent '" << effective_agent_id
|
||||
<< "', keeping current agent";
|
||||
return;
|
||||
}
|
||||
|
||||
// Swap the agent
|
||||
m_agent->set_printer_agent(new_printer_agent);
|
||||
|
||||
// Update dependent managers
|
||||
if (m_device_manager) {
|
||||
m_device_manager->set_agent(m_agent);
|
||||
|
||||
// If there's a selected machine that was deferred due to no printer agent,
|
||||
// trigger a connection now that the agent is ready
|
||||
MachineObject* selected = m_device_manager->get_selected_machine();
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": checking for deferred connection - selected="
|
||||
<< (selected ? selected->get_dev_id() : "null");
|
||||
if (selected) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": selected machine - is_lan_mode=" << selected->is_lan_mode_printer()
|
||||
<< " is_connected=" << selected->is_connected();
|
||||
}
|
||||
if (selected && selected->is_lan_mode_printer() && !selected->is_connected()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": connecting deferred LAN machine dev_id=" << selected->get_dev_id();
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
selected->connect(app_config->get("enable_ssl_for_mqtt") == "true" ? true : false);
|
||||
#else
|
||||
selected->connect(selected->local_use_ssl_for_mqtt);
|
||||
#endif
|
||||
selected->set_lan_mode_connection_state(true);
|
||||
}
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": m_device_manager is null, cannot check for deferred connection";
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": printer agent switched to " << effective_agent_id;
|
||||
}
|
||||
|
||||
bool GUI_App::dark_mode()
|
||||
{
|
||||
#ifdef SUPPORT_DARK_MODE
|
||||
@@ -4283,10 +4370,14 @@ void GUI_App::get_login_info()
|
||||
GUI::wxGetApp().run_script(strJS);
|
||||
}
|
||||
else {
|
||||
m_agent->user_logout();
|
||||
std::string logout_cmd = m_agent->build_logout_cmd();
|
||||
wxString strJS = wxString::Format("window.postMessage(%s)", logout_cmd);
|
||||
GUI::wxGetApp().run_script(strJS);
|
||||
// OrcaNetwork performs async refresh on startup; avoid clearing
|
||||
// persisted tokens when the UI polls before refresh completes.
|
||||
if (m_agent->get_version() != "orca_network") {
|
||||
m_agent->user_logout();
|
||||
std::string logout_cmd = m_agent->build_logout_cmd();
|
||||
wxString strJS = wxString::Format("window.postMessage(%s)", logout_cmd);
|
||||
GUI::wxGetApp().run_script(strJS);
|
||||
}
|
||||
}
|
||||
mainframe->m_webview->SetLoginPanelVisibility(true);
|
||||
}
|
||||
@@ -5635,7 +5726,7 @@ void GUI_App::sync_preset(Preset* preset)
|
||||
if (!new_setting_id.empty()) {
|
||||
setting_id = new_setting_id;
|
||||
result = 0;
|
||||
auto update_time_str = values_map[BBL_JSON_KEY_UPDATE_TIME];
|
||||
auto update_time_str = values_map[ORCA_JSON_KEY_UPDATE_TIME];
|
||||
if (!update_time_str.empty())
|
||||
update_time = std::atoll(update_time_str.c_str());
|
||||
}
|
||||
@@ -5664,7 +5755,7 @@ void GUI_App::sync_preset(Preset* preset)
|
||||
if (!new_setting_id.empty()) {
|
||||
setting_id = new_setting_id;
|
||||
result = 0;
|
||||
auto update_time_str = values_map[BBL_JSON_KEY_UPDATE_TIME];
|
||||
auto update_time_str = values_map[ORCA_JSON_KEY_UPDATE_TIME];
|
||||
if (!update_time_str.empty())
|
||||
update_time = std::atoll(update_time_str.c_str());
|
||||
} else {
|
||||
@@ -5690,16 +5781,16 @@ void GUI_App::sync_preset(Preset* preset)
|
||||
result = 0;
|
||||
}
|
||||
else {
|
||||
result = m_agent->put_setting(setting_id, preset->name, &values_map, &http_code);
|
||||
if (http_code >= 400) {
|
||||
result = 0;
|
||||
updated_info = "hold";
|
||||
BOOST_LOG_TRIVIAL(error) << "[sync_preset] put setting_id = " << setting_id << " failed, http_code = " << http_code;
|
||||
} else {
|
||||
auto update_time_str = values_map[BBL_JSON_KEY_UPDATE_TIME];
|
||||
result = m_agent->put_setting(setting_id, preset->name, &values_map, &http_code);
|
||||
if (http_code >= 400) {
|
||||
result = 0;
|
||||
updated_info = "hold";
|
||||
BOOST_LOG_TRIVIAL(error) << "[sync_preset] put setting_id = " << setting_id << " failed, http_code = " << http_code;
|
||||
} else {
|
||||
auto update_time_str = values_map[ORCA_JSON_KEY_UPDATE_TIME];
|
||||
if (!update_time_str.empty())
|
||||
update_time = std::atoll(update_time_str.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5752,6 +5843,8 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
||||
return;
|
||||
|
||||
if (!m_agent || !m_agent->is_user_login()) return;
|
||||
if(!m_agent->get_cloud_agent())
|
||||
return;
|
||||
|
||||
// has already start sync
|
||||
if (m_user_sync_token) return;
|
||||
@@ -5801,7 +5894,7 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
|
||||
auto type = info[BBL_JSON_KEY_TYPE];
|
||||
auto name = info[BBL_JSON_KEY_NAME];
|
||||
auto setting_id = info[BBL_JSON_KEY_SETTING_ID];
|
||||
auto update_time_str = info[BBL_JSON_KEY_UPDATE_TIME];
|
||||
auto update_time_str = info[ORCA_JSON_KEY_UPDATE_TIME];
|
||||
long long update_time = 0;
|
||||
if (!update_time_str.empty())
|
||||
update_time = std::atoll(update_time_str.c_str());
|
||||
@@ -5911,6 +6004,25 @@ void GUI_App::start_http_server()
|
||||
if (!m_http_server.is_started())
|
||||
m_http_server.start();
|
||||
}
|
||||
|
||||
void GUI_App::start_http_server(int port)
|
||||
{
|
||||
if (port <= 0) {
|
||||
start_http_server();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_http_server.is_started()) {
|
||||
if (m_http_server.get_port() == static_cast<boost::asio::ip::port_type>(port)) {
|
||||
return;
|
||||
}
|
||||
m_http_server.stop();
|
||||
}
|
||||
|
||||
m_http_server.set_port(static_cast<boost::asio::ip::port_type>(port));
|
||||
m_http_server.start();
|
||||
}
|
||||
|
||||
void GUI_App::stop_http_server()
|
||||
{
|
||||
m_http_server.stop();
|
||||
|
||||
@@ -340,6 +340,10 @@ public:
|
||||
Slic3r::TaskManager* getTaskManager() { return m_task_manager; }
|
||||
HMSQuery* get_hms_query() { return hms_query; }
|
||||
NetworkAgent* getAgent() { return m_agent; }
|
||||
|
||||
// Dynamic printer agent switching
|
||||
void switch_printer_agent(const std::string& agent_id);
|
||||
|
||||
FilamentColorCodeQuery* get_filament_color_code_query();
|
||||
bool is_editor() const { return m_app_mode == EAppMode::Editor; }
|
||||
bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; }
|
||||
@@ -501,6 +505,7 @@ public:
|
||||
void start_sync_user_preset(bool with_progress_dlg = false);
|
||||
void stop_sync_user_preset();
|
||||
void start_http_server();
|
||||
void start_http_server(int port);
|
||||
void stop_http_server();
|
||||
void switch_staff_pick(bool on);
|
||||
|
||||
|
||||
@@ -182,6 +182,42 @@ std::shared_ptr<HttpServer::Response> HttpServer::bbl_auth_handle_request(const
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "thirdparty_login: get_response";
|
||||
|
||||
const std::string auth_code = url_get_param(url, "code");
|
||||
if (!auth_code.empty()) {
|
||||
std::string state = url_get_param(url, "state");
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (!agent) {
|
||||
return std::make_shared<ResponseNotFound>();
|
||||
}
|
||||
|
||||
json payload;
|
||||
payload["command"] = "user_login";
|
||||
payload["data"]["code"] = auth_code;
|
||||
payload["data"]["state"] = state;
|
||||
|
||||
agent->change_user(payload.dump());
|
||||
const bool login_ok = agent->is_user_login();
|
||||
if (login_ok) {
|
||||
wxGetApp().request_user_login(1);
|
||||
GUI::wxGetApp().CallAfter([] { wxGetApp().ShowUserLogin(false); });
|
||||
}
|
||||
|
||||
const std::string title = login_ok ? "Authentication complete" : "Authentication failed";
|
||||
const std::string message = login_ok
|
||||
? "You can return to OrcaSlicer. This window will close automatically."
|
||||
: "Something went wrong. Please return to OrcaSlicer and try again.";
|
||||
const std::string html =
|
||||
"<html><head><meta charset=\"utf-8\">"
|
||||
"<style>body{font-family:Arial,sans-serif;background:#f7f7f7;color:#222;margin:32px;}"
|
||||
"a.button{display:inline-block;padding:10px 16px;margin-top:12px;background:#0f8bff;color:#fff;text-decoration:none;border-radius:6px;}"
|
||||
"</style></head><body><div class=\"container\">"
|
||||
"<h2>" + title + "</h2>"
|
||||
"<p>" + message + "</p>"
|
||||
"<script>setTimeout(function(){try{window.close();}catch(e){}},1500);</script>"
|
||||
"</div></body></html>";
|
||||
return std::make_shared<ResponseHtml>(html);
|
||||
}
|
||||
|
||||
if (boost::contains(url, "access_token")) {
|
||||
std::string redirect_url = url_get_param(url, "redirect_url");
|
||||
std::string access_token = url_get_param(url, "access_token");
|
||||
@@ -249,7 +285,17 @@ void HttpServer::ResponseNotFound::write_response(std::stringstream& ssOut)
|
||||
|
||||
void HttpServer::ResponseRedirect::write_response(std::stringstream& ssOut)
|
||||
{
|
||||
const std::string sHTML = "<html><body><p>redirect to url </p></body></html>";
|
||||
const std::string sHTML =
|
||||
"<html><head><meta charset=\"utf-8\">"
|
||||
"<meta http-equiv=\"refresh\" content=\"0;url=" + location_str + "\">"
|
||||
"<style>body{font-family:Arial,sans-serif;background:#f7f7f7;color:#222;margin:32px;}"
|
||||
"a.button{display:inline-block;padding:10px 16px;margin-top:12px;background:#0f8bff;color:#fff;text-decoration:none;border-radius:6px;}"
|
||||
"</style></head><body><div class=\"container\">"
|
||||
"<h2>Authentication complete</h2>"
|
||||
"<p>You can return to OrcaSlicer. If your browser does not redirect automatically, use the button below.</p>"
|
||||
"<a class=\"button\" href=\"" + location_str + "\">Continue</a>"
|
||||
"<script>setTimeout(function(){try{window.close();}catch(e){}},1500);</script>"
|
||||
"</div></body></html>";
|
||||
ssOut << "HTTP/1.1 302 Found" << std::endl;
|
||||
ssOut << "Location: " << location_str << std::endl;
|
||||
ssOut << "content-type: text/html" << std::endl;
|
||||
@@ -258,5 +304,14 @@ void HttpServer::ResponseRedirect::write_response(std::stringstream& ssOut)
|
||||
ssOut << sHTML;
|
||||
}
|
||||
|
||||
void HttpServer::ResponseHtml::write_response(std::stringstream& ssOut)
|
||||
{
|
||||
ssOut << "HTTP/1.1 200 OK" << std::endl;
|
||||
ssOut << "content-type: text/html" << std::endl;
|
||||
ssOut << "content-length: " << html.length() << std::endl;
|
||||
ssOut << std::endl;
|
||||
ssOut << html;
|
||||
}
|
||||
|
||||
} // GUI
|
||||
} //Slic3r
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#define LOCALHOST_PORT 13618
|
||||
#define LOCALHOST_URL "http://localhost:"
|
||||
@@ -98,6 +99,16 @@ public:
|
||||
void write_response(std::stringstream& ssOut) override;
|
||||
};
|
||||
|
||||
class ResponseHtml : public Response
|
||||
{
|
||||
const std::string html;
|
||||
|
||||
public:
|
||||
explicit ResponseHtml(std::string html) : html(std::move(html)) {}
|
||||
~ResponseHtml() override = default;
|
||||
void write_response(std::stringstream& ssOut) override;
|
||||
};
|
||||
|
||||
HttpServer(boost::asio::ip::port_type port = LOCALHOST_PORT);
|
||||
|
||||
boost::thread m_http_server_thread;
|
||||
@@ -106,6 +117,8 @@ public:
|
||||
bool is_started() { return start_http_server; }
|
||||
void start();
|
||||
void stop();
|
||||
void set_port(boost::asio::ip::port_type new_port) { port = new_port; }
|
||||
boost::asio::ip::port_type get_port() const { return port; }
|
||||
void set_request_handler(const std::function<std::shared_ptr<Response>(const std::string&)>& m_request_handler);
|
||||
|
||||
static std::shared_ptr<Response> bbl_auth_handle_request(const std::string& url);
|
||||
|
||||
@@ -66,22 +66,22 @@ void BindJob::process(Ctl &ctl)
|
||||
result_code = code;
|
||||
result_info = info;
|
||||
|
||||
if (stage == BBL::BindJobStage::LoginStageConnect) {
|
||||
if (stage == BindJobStage::LoginStageConnect) {
|
||||
curr_percent = 15;
|
||||
msg = _u8L("Logging in");
|
||||
} else if (stage == BBL::BindJobStage::LoginStageLogin) {
|
||||
} else if (stage == BindJobStage::LoginStageLogin) {
|
||||
curr_percent = 30;
|
||||
msg = _u8L("Logging in");
|
||||
} else if (stage == BBL::BindJobStage::LoginStageWaitForLogin) {
|
||||
} else if (stage == BindJobStage::LoginStageWaitForLogin) {
|
||||
curr_percent = 45;
|
||||
msg = _u8L("Logging in");
|
||||
} else if (stage == BBL::BindJobStage::LoginStageGetIdentify) {
|
||||
} else if (stage == BindJobStage::LoginStageGetIdentify) {
|
||||
curr_percent = 60;
|
||||
msg = _u8L("Logging in");
|
||||
} else if (stage == BBL::BindJobStage::LoginStageWaitAuth) {
|
||||
} else if (stage == BindJobStage::LoginStageWaitAuth) {
|
||||
curr_percent = 80;
|
||||
msg = _u8L("Logging in");
|
||||
} else if (stage == BBL::BindJobStage::LoginStageFinished) {
|
||||
} else if (stage == BindJobStage::LoginStageFinished) {
|
||||
curr_percent = 100;
|
||||
msg = _u8L("Logging in");
|
||||
} else {
|
||||
|
||||
@@ -197,7 +197,7 @@ void PrintJob::process(Ctl &ctl)
|
||||
this->task_bed_type = bed_type_to_gcode_string(plate_data.is_valid ? plate_data.bed_type : curr_plate->get_bed_type(true));
|
||||
}
|
||||
|
||||
BBL::PrintParams params;
|
||||
PrintParams params;
|
||||
|
||||
// local print access
|
||||
params.dev_ip = m_dev_ip;
|
||||
@@ -382,14 +382,14 @@ void PrintJob::process(Ctl &ctl)
|
||||
StagePercentPoint
|
||||
](int stage, int code, std::string info) {
|
||||
|
||||
if (stage == BBL::SendingPrintJobStage::PrintingStageCreate && !is_try_lan_mode_failed) {
|
||||
if (stage == SendingPrintJobStage::PrintingStageCreate && !is_try_lan_mode_failed) {
|
||||
if (this->connection_type == "lan") {
|
||||
msg = _u8L("Sending print job over LAN");
|
||||
} else {
|
||||
msg = _u8L("Sending print job through cloud service");
|
||||
}
|
||||
}
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageUpload && !is_try_lan_mode_failed) {
|
||||
else if (stage == SendingPrintJobStage::PrintingStageUpload && !is_try_lan_mode_failed) {
|
||||
if (code >= 0 && code <= 100 && !info.empty()) {
|
||||
if (this->connection_type == "lan") {
|
||||
msg = _u8L("Sending print job over LAN");
|
||||
@@ -399,24 +399,24 @@ void PrintJob::process(Ctl &ctl)
|
||||
msg += format("(%s)", info);
|
||||
}
|
||||
}
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageWaiting) {
|
||||
else if (stage == SendingPrintJobStage::PrintingStageWaiting) {
|
||||
if (this->connection_type == "lan") {
|
||||
msg = _u8L("Sending print job over LAN");
|
||||
} else {
|
||||
msg = _u8L("Sending print job through cloud service");
|
||||
}
|
||||
}
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageRecord && !is_try_lan_mode) {
|
||||
else if (stage == SendingPrintJobStage::PrintingStageRecord && !is_try_lan_mode) {
|
||||
msg = _u8L("Sending print configuration");
|
||||
}
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageSending && !is_try_lan_mode) {
|
||||
else if (stage == SendingPrintJobStage::PrintingStageSending && !is_try_lan_mode) {
|
||||
if (this->connection_type == "lan") {
|
||||
msg = _u8L("Sending print job over LAN");
|
||||
} else {
|
||||
msg = _u8L("Sending print job through cloud service");
|
||||
}
|
||||
}
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageFinished) {
|
||||
else if (stage == SendingPrintJobStage::PrintingStageFinished) {
|
||||
msg = format(_u8L("Successfully sent. Will automatically jump to the device page in %ss"), info);
|
||||
if (m_print_job_completed_id == wxGetApp().plater()->get_send_calibration_finished_event()) {
|
||||
msg = format(_u8L("Successfully sent. Will automatically jump to the next page in %ss"), info);
|
||||
@@ -433,15 +433,15 @@ void PrintJob::process(Ctl &ctl)
|
||||
// update current percnet
|
||||
if (stage >= 0 && stage <= (int) PrintingStageFinished) {
|
||||
curr_percent = StagePercentPoint[stage];
|
||||
if ((stage == BBL::SendingPrintJobStage::PrintingStageUpload
|
||||
|| stage == BBL::SendingPrintJobStage::PrintingStageRecord)
|
||||
if ((stage == SendingPrintJobStage::PrintingStageUpload
|
||||
|| stage == SendingPrintJobStage::PrintingStageRecord)
|
||||
&& (code > 0 && code <= 100)) {
|
||||
curr_percent = (StagePercentPoint[stage + 1] - StagePercentPoint[stage]) * code / 100 + StagePercentPoint[stage];
|
||||
}
|
||||
}
|
||||
|
||||
//get errors
|
||||
if (code > 100 || code < 0 || stage == BBL::SendingPrintJobStage::PrintingStageERROR) {
|
||||
if (code > 100 || code < 0 || stage == SendingPrintJobStage::PrintingStageERROR) {
|
||||
if (code == BAMBU_NETWORK_ERR_PRINT_WR_FILE_OVER_SIZE || code == BAMBU_NETWORK_ERR_PRINT_SP_FILE_OVER_SIZE) {
|
||||
m_plater->update_print_error_info(code, desc_file_too_large, info);
|
||||
}else if (code == BAMBU_NETWORK_ERR_PRINT_WR_FILE_NOT_EXIST || code == BAMBU_NETWORK_ERR_PRINT_SP_FILE_NOT_EXIST){
|
||||
|
||||
@@ -100,10 +100,10 @@ inline std::string get_transform_string(int bytes)
|
||||
|
||||
void SendJob::process(Ctl &ctl)
|
||||
{
|
||||
BBL::PrintParams params;
|
||||
PrintParams params;
|
||||
std::string msg;
|
||||
int curr_percent = 10;
|
||||
NetworkAgent* m_agent = wxGetApp().getAgent();
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
AppConfig* config = wxGetApp().app_config;
|
||||
int result = -1;
|
||||
std::string http_body;
|
||||
@@ -234,14 +234,14 @@ void SendJob::process(Ctl &ctl)
|
||||
// update current percnet
|
||||
if (stage >= 0 && stage <= (int) PrintingStageFinished) {
|
||||
curr_percent = StagePercentPoint[stage];
|
||||
if ((stage == BBL::SendingPrintJobStage::PrintingStageUpload) &&
|
||||
if ((stage == SendingPrintJobStage::PrintingStageUpload) &&
|
||||
(code > 0 && code <= 100)) {
|
||||
curr_percent = (StagePercentPoint[stage + 1] - StagePercentPoint[stage]) * code / 100 + StagePercentPoint[stage];
|
||||
}
|
||||
}
|
||||
|
||||
//get errors
|
||||
if (code > 100 || code < 0 || stage == BBL::SendingPrintJobStage::PrintingStageERROR) {
|
||||
if (code > 100 || code < 0 || stage == SendingPrintJobStage::PrintingStageERROR) {
|
||||
if (code == BAMBU_NETWORK_ERR_PRINT_WR_FILE_OVER_SIZE || code == BAMBU_NETWORK_ERR_PRINT_SP_FILE_OVER_SIZE) {
|
||||
m_plater->update_print_error_info(code, desc_file_too_large, info);
|
||||
}
|
||||
@@ -281,7 +281,7 @@ void SendJob::process(Ctl &ctl)
|
||||
// try to send local with record
|
||||
BOOST_LOG_TRIVIAL(info) << "send_job: try to send gcode to printer";
|
||||
ctl.update_status(curr_percent, _u8L("Sending G-code file over LAN"));
|
||||
result = m_agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn, nullptr);
|
||||
result = agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn, nullptr);
|
||||
if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
|
||||
params.comments = "upload_failed";
|
||||
} else {
|
||||
@@ -304,8 +304,8 @@ void SendJob::process(Ctl &ctl)
|
||||
case DevStorage::SdcardState::HAS_SDCARD_ABNORMAL:
|
||||
if(this->has_sdcard) {
|
||||
// means the sdcard is abnormal but can be used option is enabled
|
||||
ctl.update_status(curr_percent, _u8L("Sending G-code file over LAN, but the Storage in the printer is abnormal and print-issues may be caused by this."));
|
||||
result = m_agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn, nullptr);
|
||||
ctl.update_status(curr_percent, _u8L("Sending G-code file over LAN, but the Storage in the printer is abnormal and print-issues may be caused by this."));
|
||||
result = agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn, nullptr);
|
||||
break;
|
||||
}
|
||||
ctl.update_status(curr_percent, _u8L("The Storage in the printer is abnormal. Please replace it with a normal Storage before sending to printer."));
|
||||
@@ -315,7 +315,7 @@ void SendJob::process(Ctl &ctl)
|
||||
return;
|
||||
case DevStorage::SdcardState::HAS_SDCARD_NORMAL:
|
||||
ctl.update_status(curr_percent, _u8L("Sending G-code file over LAN"));
|
||||
result = m_agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn, nullptr);
|
||||
result = agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn, nullptr);
|
||||
break;
|
||||
default:
|
||||
ctl.update_status(curr_percent, _u8L("Encountered an unknown error with the Storage status. Please try again."));
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "I18N.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "DownloadProgressDialog.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "slic3r/Utils/bambu_networking.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/button.h>
|
||||
@@ -532,8 +533,8 @@ void MonitorPanel::update_network_version_footer()
|
||||
return;
|
||||
|
||||
std::string configured_version = wxGetApp().app_config->get_network_plugin_version();
|
||||
std::string suffix = BBL::extract_suffix(configured_version);
|
||||
std::string configured_base = BBL::extract_base_version(configured_version);
|
||||
std::string suffix = extract_suffix(configured_version);
|
||||
std::string configured_base = extract_base_version(configured_version);
|
||||
|
||||
wxString footer_text;
|
||||
if (!suffix.empty() && configured_base == binary_version) {
|
||||
|
||||
@@ -211,7 +211,7 @@ void NetworkPluginDownloadDialog::setup_version_selector()
|
||||
wxDefaultPosition, wxSize(FromDIP(380), FromDIP(28)), 0, nullptr, wxCB_READONLY);
|
||||
m_version_combo->SetFont(::Label::Body_13);
|
||||
|
||||
m_available_versions = BBL::get_all_available_versions();
|
||||
m_available_versions = get_all_available_versions();
|
||||
for (size_t i = 0; i < m_available_versions.size(); ++i) {
|
||||
const auto& ver = m_available_versions[i];
|
||||
wxString label;
|
||||
|
||||
@@ -53,7 +53,7 @@ private:
|
||||
wxCollapsiblePane* m_details_pane{nullptr};
|
||||
std::string m_error_message;
|
||||
std::string m_error_details;
|
||||
std::vector<BBL::NetworkLibraryVersionInfo> m_available_versions;
|
||||
std::vector<NetworkLibraryVersionInfo> m_available_versions;
|
||||
};
|
||||
|
||||
class NetworkPluginRestartDialog : public DPIDialog
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "slic3r/Utils/NetworkAgentFactory.hpp"
|
||||
#include "format.hpp"
|
||||
#include "Tab.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
@@ -124,8 +125,22 @@ PhysicalPrinterDialog::~PhysicalPrinterDialog()
|
||||
void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgroup)
|
||||
{
|
||||
m_optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
|
||||
if (opt_key == "host_type" || opt_key == "printhost_authorization_type")
|
||||
// Special handling for printer_agent: convert fake enum index to string agent ID
|
||||
if (opt_key == "printer_agent") {
|
||||
try {
|
||||
int selected_idx = boost::any_cast<int>(value);
|
||||
auto agents = NetworkAgentFactory::get_registered_printer_agents();
|
||||
if (selected_idx >= 0 && selected_idx < static_cast<int>(agents.size())) {
|
||||
m_config->set_key_value("printer_agent",
|
||||
new ConfigOptionString(agents[selected_idx].id));
|
||||
}
|
||||
} catch (const boost::bad_any_cast&) {
|
||||
// If value is not an int, ignore
|
||||
}
|
||||
this->update();
|
||||
} else if (opt_key == "host_type" || opt_key == "printhost_authorization_type") {
|
||||
this->update();
|
||||
}
|
||||
if (opt_key == "print_host")
|
||||
this->update_printhost_buttons();
|
||||
if (opt_key == "printhost_port")
|
||||
@@ -136,6 +151,55 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
|
||||
|
||||
m_optgroup->append_single_option_line("host_type");
|
||||
|
||||
// Build printer agent dropdown from registry (only if network agent is available)
|
||||
if (wxGetApp().getAgent() != nullptr) {
|
||||
auto agents = NetworkAgentFactory::get_registered_printer_agents();
|
||||
|
||||
if (!agents.empty()) {
|
||||
// Create a fake enum option to force a Choice widget instead of TextCtrl
|
||||
// (printer_agent is coString in config, but we need a dropdown)
|
||||
ConfigOptionDef def;
|
||||
def.type = coEnum;
|
||||
def.width = Field::def_width();
|
||||
def.label = L("Printer Agent");
|
||||
def.tooltip = L("Select the network agent implementation for printer communication. "
|
||||
"Available agents are registered at startup.");
|
||||
def.mode = comAdvanced;
|
||||
|
||||
// Populate enum values and labels from registered agents
|
||||
for (const auto& agent : agents) {
|
||||
def.enum_values.push_back(agent.id);
|
||||
def.enum_labels.push_back(agent.display_name);
|
||||
}
|
||||
|
||||
// Set initial selection based on current config value or default
|
||||
const std::string current_agent = m_config->opt_string("printer_agent");
|
||||
std::string selected_agent = current_agent;
|
||||
|
||||
if (selected_agent.empty()) {
|
||||
selected_agent = NetworkAgentFactory::get_default_printer_agent_id();
|
||||
}
|
||||
|
||||
// Verify selected agent is valid
|
||||
auto it = std::find_if(agents.begin(), agents.end(), [&selected_agent](const auto& a) { return a.id == selected_agent; });
|
||||
if (it == agents.end()) {
|
||||
selected_agent = NetworkAgentFactory::get_default_printer_agent_id();
|
||||
}
|
||||
|
||||
// Set default value for the enum (using the index)
|
||||
auto def_it = std::find_if(agents.begin(), agents.end(), [&selected_agent](const auto& a) { return a.id == selected_agent; });
|
||||
if (def_it != agents.end()) {
|
||||
size_t default_idx = std::distance(agents.begin(), def_it);
|
||||
def.set_default_value(new ConfigOptionInt(static_cast<int>(default_idx)));
|
||||
}
|
||||
|
||||
// Create and append the option line
|
||||
auto agent_option = Option(def, "printer_agent");
|
||||
Line agent_line = m_optgroup->create_single_option_line(agent_option);
|
||||
m_optgroup->append_line(agent_line);
|
||||
}
|
||||
}
|
||||
|
||||
auto create_sizer_with_btn = [](wxWindow* parent, Button** btn, const std::string& icon_name, const wxString& label) {
|
||||
*btn = new Button(parent, label);
|
||||
(*btn)->SetStyle(ButtonStyle::Regular, ButtonType::Parameter);
|
||||
@@ -688,6 +752,31 @@ void PhysicalPrinterDialog::update_host_type(bool printer_change)
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::update_printer_agent_type()
|
||||
{
|
||||
if (m_config == nullptr)
|
||||
return;
|
||||
|
||||
Field* agent_field = m_optgroup->get_field("printer_agent");
|
||||
if (!agent_field)
|
||||
return;
|
||||
|
||||
Choice* agent_choice = dynamic_cast<Choice*>(agent_field);
|
||||
if (!agent_choice)
|
||||
return;
|
||||
|
||||
// Sync selection with current config value
|
||||
const std::string current_agent = m_config->opt_string("printer_agent");
|
||||
|
||||
auto agents = NetworkAgentFactory::get_registered_printer_agents();
|
||||
for (size_t i = 0; i < agents.size(); ++i) {
|
||||
if (agents[i].id == current_agent) {
|
||||
agent_choice->set_value(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::update_printers()
|
||||
{
|
||||
wxBusyCursor wait;
|
||||
|
||||
@@ -60,6 +60,7 @@ public:
|
||||
|
||||
void update(bool printer_change = false);
|
||||
void update_host_type(bool printer_change);
|
||||
void update_printer_agent_type();
|
||||
void update_preset_input();
|
||||
void update_printhost_buttons();
|
||||
void update_printers();
|
||||
|
||||
@@ -2371,7 +2371,14 @@ void Sidebar::update_all_preset_comboboxes()
|
||||
} else {
|
||||
//p->btn_connect_printer->Show();
|
||||
p->m_printer_connect->Show();
|
||||
p->m_bpButton_ams_filament->Hide();
|
||||
|
||||
// ORCA: show/hide sync-ams button based on filament sync mode
|
||||
auto agent = wxGetApp().getAgent();
|
||||
if (agent && agent->get_filament_sync_mode() != FilamentSyncMode::none)
|
||||
p->m_bpButton_ams_filament->Show();
|
||||
else
|
||||
p->m_bpButton_ams_filament->Hide();
|
||||
|
||||
auto print_btn_type = MainFrame::PrintSelectType::eExportGcode;
|
||||
wxString url = cfg.opt_string("print_host_webui").empty() ? cfg.opt_string("print_host") : cfg.opt_string("print_host_webui");
|
||||
wxString apikey;
|
||||
@@ -3161,11 +3168,49 @@ void Sidebar::on_bed_type_change(BedType bed_type)
|
||||
p->combo_printer_bed->SetSelection(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a map of filament configurations from the connected printer's AMS (Automatic Material System).
|
||||
*
|
||||
* Data Flow Architecture:
|
||||
* =======================
|
||||
* This function reads pre-populated state from MachineObject - it does NOT directly call
|
||||
* NetworkAgent APIs. The data pipeline is:
|
||||
*
|
||||
* Printer Device (MQTT/LAN messages)
|
||||
* ↓
|
||||
* NetworkAgent (receives JSON, triggers OnMessageFn callbacks)
|
||||
* ↓
|
||||
* MachineObject::parse_json() (updates device state)
|
||||
* ├── vt_slot (std::vector<DevAmsTray>) - virtual tray data for external filament
|
||||
* └── DevFilaSystem → DevAms → DevAmsTray - AMS unit hierarchy
|
||||
* ↓
|
||||
* build_filament_ams_list() [THIS FUNCTION] - aggregates into DynamicPrintConfig maps
|
||||
*
|
||||
* Data Sources:
|
||||
* - obj->vt_slot: Virtual trays for external/manual filament loading (when ams_support_virtual_tray is true)
|
||||
* - obj->GetFilaSystem()->GetAmsList(): Map of AMS units, each containing multiple DevAmsTray slots
|
||||
*
|
||||
* Return Value:
|
||||
* - Map key encoding:
|
||||
* - Virtual trays: 0x10000 + vt_tray.id (first/main extruder), or just vt_tray.id (secondary)
|
||||
* - AMS trays: 0x10000 + (ams_id * 4 + slot_id) (main extruder), or (ams_id * 4 + slot_id) (secondary)
|
||||
* - The 0x10000 flag indicates the main/right extruder
|
||||
* - Map value: DynamicPrintConfig with filament properties (id, type, color, etc.)
|
||||
*
|
||||
* @param obj The MachineObject representing the connected printer (nullable)
|
||||
* @return Map of tray indices to filament configurations
|
||||
*/
|
||||
std::map<int, DynamicPrintConfig> Sidebar::build_filament_ams_list(MachineObject* obj)
|
||||
{
|
||||
std::map<int, DynamicPrintConfig> filament_ams_list;
|
||||
if (!obj) return filament_ams_list;
|
||||
|
||||
// For pull-mode agents (e.g., HTTP REST API), refresh DevFilaSystem first
|
||||
auto* agent = wxGetApp().getDeviceManager()->get_agent();
|
||||
if (agent && agent->get_filament_sync_mode() == FilamentSyncMode::pull) {
|
||||
agent->fetch_filament_info(obj->get_dev_id());
|
||||
}
|
||||
|
||||
auto build_tray_config = [](DevAmsTray const &tray, std::string const &name, std::string ams_id, std::string slot_id) {
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("build_filament_ams_list: name %1% setting_id %2% type %3% color %4%")
|
||||
% name % tray.setting_id % tray.m_fila_type % tray.color;
|
||||
@@ -3285,7 +3330,14 @@ void Sidebar::get_small_btn_sync_pos_size(wxPoint &pt, wxSize &size) {
|
||||
|
||||
void Sidebar::load_ams_list(MachineObject* obj)
|
||||
{
|
||||
std::map<int, DynamicPrintConfig> filament_ams_list = build_filament_ams_list(obj);
|
||||
std::map<int, DynamicPrintConfig> filament_ams_list;
|
||||
|
||||
// build_filament_ams_list handles both subscription-based and non-subscription-based agents:
|
||||
// - For non-subscription agents, it calls fetch_filament_info() first to populate DevFilaSystem
|
||||
// - Then it always reads from DevFilaSystem to build the filament list
|
||||
if (obj) {
|
||||
filament_ams_list = build_filament_ams_list(obj);
|
||||
}
|
||||
|
||||
bool device_change = false;
|
||||
const std::string& device = obj ? obj->get_dev_id() : "";
|
||||
@@ -3315,8 +3367,9 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn)
|
||||
wxBusyCursor cursor;
|
||||
// Force load ams list
|
||||
auto obj = wxGetApp().getDeviceManager()->get_selected_machine();
|
||||
if (obj)
|
||||
GUI::wxGetApp().sidebar().load_ams_list(obj);
|
||||
if (!obj)
|
||||
return;
|
||||
GUI::wxGetApp().sidebar().load_ams_list(obj);
|
||||
|
||||
auto & list = wxGetApp().preset_bundle->filament_ams_list;
|
||||
if (list.empty()) {
|
||||
@@ -15134,7 +15187,7 @@ int Plater::export_3mf(const boost::filesystem::path& output_path, SaveStrategy
|
||||
// set designInfo before export and reset after export
|
||||
if (wxGetApp().is_user_login()) {
|
||||
p->model.design_info = std::make_shared<ModelDesignInfo>();
|
||||
//p->model.design_info->Designer = wxGetApp().getAgent()->get_user_nickanme();
|
||||
//p->model.design_info->Designer = wxGetApp().getAgent()->get_user_nickname();
|
||||
p->model.design_info->Designer = "";
|
||||
p->model.design_info->DesignerUserId = wxGetApp().getAgent()->get_user_id();
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info prepare, designer = "<< "";
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "Widgets/StaticLine.hpp"
|
||||
#include "Widgets/RadioGroup.hpp"
|
||||
#include "slic3r/Utils/bambu_networking.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
#include "DownloadProgressDialog.hpp"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
@@ -1411,6 +1412,11 @@ void PreferencesDialog::create_items()
|
||||
auto item_system_sync = create_item_checkbox(_L("Update built-in Presets automatically."), "", "sync_system_preset");
|
||||
g_sizer->Add(item_system_sync);
|
||||
|
||||
auto item_token_storage = create_item_checkbox(_L("Use encrypted file for token storage"),
|
||||
_L("Store authentication tokens in an encrypted file instead of the system keychain. (Requires restart)"),
|
||||
SETTING_USE_ENCRYPTED_TOKEN_FILE);
|
||||
g_sizer->Add(item_token_storage);
|
||||
|
||||
//// ONLINE > Network plugin
|
||||
g_sizer->Add(create_item_title(_L("Network plugin")), 1, wxEXPAND);
|
||||
|
||||
@@ -1433,11 +1439,11 @@ void PreferencesDialog::create_items()
|
||||
|
||||
std::string current_version = app_config->get_network_plugin_version();
|
||||
if (current_version.empty()) {
|
||||
current_version = BBL::get_latest_network_version();
|
||||
current_version = get_latest_network_version();
|
||||
}
|
||||
int current_selection = 0;
|
||||
|
||||
m_available_versions = BBL::get_all_available_versions();
|
||||
m_available_versions = get_all_available_versions();
|
||||
|
||||
for (size_t i = 0; i < m_available_versions.size(); i++) {
|
||||
const auto& ver = m_available_versions[i];
|
||||
@@ -1468,7 +1474,7 @@ void PreferencesDialog::create_items()
|
||||
std::string new_version = selected_ver.version;
|
||||
std::string old_version = app_config->get_network_plugin_version();
|
||||
if (old_version.empty()) {
|
||||
old_version = BBL::get_latest_network_version();
|
||||
old_version = get_latest_network_version();
|
||||
}
|
||||
|
||||
app_config->set(SETTING_NETWORK_PLUGIN_VERSION, new_version);
|
||||
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
::TextInput *m_backup_interval_textinput = {nullptr};
|
||||
::ComboBox * m_network_version_combo = {nullptr};
|
||||
wxBoxSizer * m_network_version_sizer = {nullptr};
|
||||
std::vector<BBL::NetworkLibraryVersionInfo> m_available_versions;
|
||||
std::vector<NetworkLibraryVersionInfo> m_available_versions;
|
||||
|
||||
wxString m_developer_mode_def;
|
||||
wxString m_internal_developer_mode_def;
|
||||
|
||||
@@ -439,9 +439,9 @@ void SendMultiMachinePage::refresh_user_device()
|
||||
Fit();
|
||||
}
|
||||
|
||||
BBL::PrintParams SendMultiMachinePage::request_params(MachineObject* obj)
|
||||
PrintParams SendMultiMachinePage::request_params(MachineObject* obj)
|
||||
{
|
||||
BBL::PrintParams params;
|
||||
PrintParams params;
|
||||
|
||||
//get all setting
|
||||
bool bed_leveling = app_config->get("print", "bed_leveling") == "1" ? true : false;
|
||||
@@ -734,7 +734,7 @@ void SendMultiMachinePage::on_send(wxCommandEvent& event)
|
||||
}
|
||||
|
||||
|
||||
std::vector<BBL::PrintParams> print_params;
|
||||
std::vector<PrintParams> print_params;
|
||||
|
||||
for (auto it = m_device_items.begin(); it != m_device_items.end(); ++it) {
|
||||
auto obj = it->second->get_obj();
|
||||
@@ -742,7 +742,7 @@ void SendMultiMachinePage::on_send(wxCommandEvent& event)
|
||||
if (obj && obj->is_online() && !obj->can_abort() && !obj->is_in_upgrading() && it->second->get_state_selected() == 1 && it->second->state_printable <= 2) {
|
||||
|
||||
if (!it->second->is_blocking_printing(obj)) {
|
||||
BBL::PrintParams params = request_params(obj);
|
||||
PrintParams params = request_params(obj);
|
||||
print_params.push_back(params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
void on_send(wxCommandEvent& event);
|
||||
bool Show(bool show);
|
||||
|
||||
BBL::PrintParams request_params(MachineObject* obj);
|
||||
PrintParams request_params(MachineObject* obj);
|
||||
|
||||
bool get_ams_mapping_result(std::string &mapping_array_str, std::string &mapping_array_str2, std::string &ams_mapping_info);
|
||||
wxBoxSizer* create_item_title(wxString title, wxWindow* parent, wxString tooltip);
|
||||
|
||||
@@ -2099,6 +2099,11 @@ void Tab::on_presets_changed()
|
||||
// Instead of PostEvent (EVT_TAB_PRESETS_CHANGED) just call update_presets
|
||||
wxGetApp().plater()->sidebar().update_presets(m_type);
|
||||
|
||||
// Check if printer agent needs switching
|
||||
if (m_type == Preset::TYPE_PRINTER) {
|
||||
update_printer_agent_if_needed();
|
||||
}
|
||||
|
||||
bool is_bbl_vendor_preset = m_preset_bundle->is_bbl_vendor();
|
||||
if (is_bbl_vendor_preset) {
|
||||
wxGetApp().plater()->get_partplate_list().set_render_option(true, true);
|
||||
@@ -2129,6 +2134,28 @@ void Tab::on_presets_changed()
|
||||
wxGetApp().plater()->update_project_dirty_from_presets();
|
||||
}
|
||||
|
||||
void Tab::update_printer_agent_if_needed()
|
||||
{
|
||||
std::string agent_id = "orca";
|
||||
if (m_preset_bundle) {
|
||||
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
|
||||
agent_id = "bbl";
|
||||
} else if (wxGetApp().preset_bundle->is_qidi_vendor()) {
|
||||
agent_id = "qidi";
|
||||
}
|
||||
}
|
||||
|
||||
const DynamicPrintConfig& config = m_preset_bundle->printers.get_edited_preset().config;
|
||||
if (config.has("printer_agent")) {
|
||||
std::string value = config.option<ConfigOptionString>("printer_agent")->value;
|
||||
if (!value.empty()) {
|
||||
agent_id = value;
|
||||
}
|
||||
}
|
||||
// Switch agent in GUI_App
|
||||
wxGetApp().switch_printer_agent(agent_id);
|
||||
}
|
||||
|
||||
void Tab::build_preset_description_line(ConfigOptionsGroup* optgroup)
|
||||
{
|
||||
auto description_line = [this](wxWindow* parent) {
|
||||
|
||||
@@ -437,6 +437,7 @@ protected:
|
||||
// return true if cancelled
|
||||
bool tree_sel_change_delayed(wxCommandEvent& event);
|
||||
void on_presets_changed();
|
||||
void update_printer_agent_if_needed();
|
||||
void build_preset_description_line(ConfigOptionsGroup* optgroup);
|
||||
void update_preset_description_line();
|
||||
void update_frequently_changed_parameters();
|
||||
|
||||
@@ -62,7 +62,7 @@ TaskState parse_task_status(int status)
|
||||
|
||||
int TaskStateInfo::g_task_info_id = 0;
|
||||
|
||||
TaskStateInfo::TaskStateInfo(BBL::PrintParams param)
|
||||
TaskStateInfo::TaskStateInfo(PrintParams param)
|
||||
: m_state(TaskState::TS_PENDING)
|
||||
, m_params(param)
|
||||
, m_sending_percent(0)
|
||||
@@ -103,8 +103,8 @@ TaskStateInfo::TaskStateInfo(BBL::PrintParams param)
|
||||
int curr_percent = 0;
|
||||
if (stage >= 0 && stage <= (int)PrintingStageFinished) {
|
||||
curr_percent = StagePercentPoint[stage];
|
||||
if ((stage == BBL::SendingPrintJobStage::PrintingStageUpload
|
||||
|| stage == BBL::SendingPrintJobStage::PrintingStageRecord)
|
||||
if ((stage == SendingPrintJobStage::PrintingStageUpload
|
||||
|| stage == SendingPrintJobStage::PrintingStageRecord)
|
||||
&& (code > 0 && code <= 100)) {
|
||||
curr_percent = (StagePercentPoint[stage + 1] - StagePercentPoint[stage]) * code / 100 + StagePercentPoint[stage];
|
||||
BOOST_LOG_TRIVIAL(trace) << "task_manager: percent = " << curr_percent;
|
||||
@@ -156,7 +156,7 @@ TaskManager::TaskManager(NetworkAgent* agent)
|
||||
}
|
||||
|
||||
|
||||
int TaskManager::start_print(const std::vector<BBL::PrintParams>& params, TaskSettings* settings)
|
||||
int TaskManager::start_print(const std::vector<PrintParams>& params, TaskSettings* settings)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "task_manager: start_print size = " << params.size();
|
||||
TaskManager::MaxSendingAtSameTime = settings->max_sending_at_same_time;
|
||||
@@ -173,7 +173,7 @@ int TaskManager::start_print(const std::vector<BBL::PrintParams>& params, TaskSe
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int start_print_test(BBL::PrintParams& params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
|
||||
static int start_print_test(PrintParams& params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
|
||||
{
|
||||
int tick = 2;
|
||||
for (int i = 0; i < 100 * tick; i++) {
|
||||
@@ -321,7 +321,7 @@ std::map<std::string, TaskStateInfo> TaskManager::get_task_list(int curr_page, i
|
||||
{
|
||||
std::map<std::string, TaskStateInfo> out;
|
||||
if (m_agent) {
|
||||
BBL::TaskQueryParams task_query_params;
|
||||
TaskQueryParams task_query_params;
|
||||
task_query_params.limit = page_count;
|
||||
task_query_params.offset = curr_page * page_count;
|
||||
std::string task_info;
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
static int g_task_info_id;
|
||||
typedef std::function<void(TaskState state, int percent)> StateChangedFn;
|
||||
|
||||
TaskStateInfo(const BBL::PrintParams param);
|
||||
TaskStateInfo(const PrintParams param);
|
||||
|
||||
TaskStateInfo() {
|
||||
task_info_id = ++TaskStateInfo::g_task_info_id;
|
||||
@@ -47,9 +47,9 @@ public:
|
||||
m_state_changed_fn(m_state, m_sending_percent);
|
||||
}
|
||||
}
|
||||
BBL::PrintParams get_params() { return m_params; }
|
||||
PrintParams get_params() { return m_params; }
|
||||
|
||||
BBL::PrintParams& params() { return m_params; }
|
||||
PrintParams& params() { return m_params; }
|
||||
|
||||
std::string get_job_id(){return profile_id;}
|
||||
|
||||
@@ -109,7 +109,7 @@ private:
|
||||
TaskState m_state;
|
||||
std::string m_task_name;
|
||||
std::string m_device_name;
|
||||
BBL::PrintParams m_params;
|
||||
PrintParams m_params;
|
||||
int m_sending_percent;
|
||||
std::string m_job_id;
|
||||
StateChangedFn m_state_changed_fn;
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
static int SendingInterval;
|
||||
TaskManager(NetworkAgent* agent);
|
||||
|
||||
int start_print(const std::vector<BBL::PrintParams>& params, TaskSettings* settings = nullptr);
|
||||
int start_print(const std::vector<PrintParams>& params, TaskSettings* settings = nullptr);
|
||||
|
||||
static void set_max_send_at_same_time(int count);
|
||||
|
||||
|
||||
@@ -75,15 +75,11 @@ ZUserLogin::ZUserLogin() : wxDialog((wxWindow *) (wxGetApp().mainframe), wxID_AN
|
||||
CentreOnParent();
|
||||
}
|
||||
else {
|
||||
std::string host_url = agent->get_bambulab_host();
|
||||
TargetUrl = host_url + "/sign-in";
|
||||
m_networkOk = false;
|
||||
|
||||
// Get the login URL from the cloud service agent
|
||||
wxString strlang = wxGetApp().current_language_code_safe();
|
||||
if (strlang != "") {
|
||||
strlang.Replace("_", "-");
|
||||
TargetUrl = host_url + "/" + strlang + "/sign-in";
|
||||
}
|
||||
strlang.Replace("_", "-");
|
||||
TargetUrl = wxString::FromUTF8(agent->get_cloud_login_url(strlang.ToStdString()));
|
||||
m_networkOk = TargetUrl.StartsWith("file://");
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "login url = " << TargetUrl.ToStdString();
|
||||
|
||||
@@ -225,9 +221,9 @@ void ZUserLogin::OnDocumentLoaded(wxWebViewEvent &evt)
|
||||
// Only notify if the document is the main frame, not a subframe
|
||||
wxString tmpUrl = evt.GetURL();
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
std::string strHost = agent->get_bambulab_host();
|
||||
std::string strHost = agent->get_cloud_service_host();
|
||||
|
||||
if ( tmpUrl.Contains(strHost) ) {
|
||||
if (tmpUrl.StartsWith("file://") || tmpUrl.Contains(strHost)) {
|
||||
m_networkOk = true;
|
||||
// wxLogMessage("%s", "Document loaded; url='" + evt.GetURL() + "'");
|
||||
}
|
||||
@@ -268,28 +264,97 @@ void ZUserLogin::OnFullScreenChanged(wxWebViewEvent &evt)
|
||||
void ZUserLogin::OnScriptMessage(wxWebViewEvent &evt)
|
||||
{
|
||||
wxString str_input = evt.GetString();
|
||||
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] OnScriptMessage received: " << str_input.ToStdString();
|
||||
|
||||
try {
|
||||
json j = json::parse(into_u8(str_input));
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Parsed JSON successfully";
|
||||
|
||||
wxString strCmd = j["command"];
|
||||
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Command: " << strCmd.ToStdString();
|
||||
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
if (agent && strCmd == "get_login_cmd" && agent->get_cloud_agent()) {
|
||||
// Return login config (backend_url, apikey, pkce)
|
||||
// WebView handles provider selection internally
|
||||
std::string login_cmd = agent->build_login_cmd();
|
||||
m_loopback_port = 0;
|
||||
try {
|
||||
json cfg = json::parse(login_cmd);
|
||||
if (cfg.contains("pkce")) {
|
||||
const auto& pkce = cfg["pkce"];
|
||||
if (pkce.contains("loopback_port")) {
|
||||
if (pkce["loopback_port"].is_number_integer()) {
|
||||
m_loopback_port = pkce["loopback_port"].get<int>();
|
||||
} else if (pkce["loopback_port"].is_string()) {
|
||||
m_loopback_port = std::stoi(pkce["loopback_port"].get<std::string>());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_loopback_port <= 0 && pkce.contains("redirect_uri") && pkce["redirect_uri"].is_string()) {
|
||||
const std::string redirect_uri = pkce["redirect_uri"].get<std::string>();
|
||||
const char* prefixes[] = {"localhost:", "127.0.0.1:"};
|
||||
for (const char* prefix : prefixes) {
|
||||
auto start = redirect_uri.find(prefix);
|
||||
if (start == std::string::npos)
|
||||
continue;
|
||||
start += strlen(prefix);
|
||||
auto end = redirect_uri.find('/', start);
|
||||
std::string port_str = redirect_uri.substr(start, end - start);
|
||||
try {
|
||||
m_loopback_port = std::stoi(port_str);
|
||||
} catch (...) {
|
||||
m_loopback_port = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
m_loopback_port = 0;
|
||||
}
|
||||
wxString str_js = wxString::FromUTF8("window.postMessage(") + wxString::FromUTF8(login_cmd.c_str()) +
|
||||
wxString::FromUTF8(", '*')");
|
||||
this->RunScript(str_js);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strCmd == "autotest_token")
|
||||
{
|
||||
m_AutotestToken = j["data"]["token"];
|
||||
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Stored autotest_token";
|
||||
}
|
||||
if (strCmd == "user_login") {
|
||||
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Processing user_login command";
|
||||
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] User data: " << j["data"].dump();
|
||||
|
||||
j["data"]["autotest_token"] = m_AutotestToken;
|
||||
wxGetApp().handle_script_message(j.dump());
|
||||
Close();
|
||||
std::string message_json = j.dump();
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Calling handle_script_message with: " << message_json;
|
||||
|
||||
// End modal dialog first to unblock event loop before processing callbacks
|
||||
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Ending modal dialog";
|
||||
EndModal(wxID_OK);
|
||||
|
||||
// Handle message after modal dialog ends to avoid deadlock
|
||||
// Use wxTheApp->CallAfter to ensure it runs after modal loop exits
|
||||
wxTheApp->CallAfter([message_json]() {
|
||||
BOOST_LOG_TRIVIAL(debug) << "[WebUserLoginDialog] Processing login message after modal ended";
|
||||
wxGetApp().handle_script_message(message_json);
|
||||
});
|
||||
}
|
||||
else if (strCmd == "get_localhost_url") {
|
||||
BOOST_LOG_TRIVIAL(info) << "thirdparty_login: get_localhost_url";
|
||||
wxGetApp().start_http_server();
|
||||
BOOST_LOG_TRIVIAL(debug) << "thirdparty_login: get_localhost_url";
|
||||
int loopback_port = m_loopback_port > 0 ? m_loopback_port : LOCALHOST_PORT;
|
||||
wxGetApp().start_http_server(loopback_port);
|
||||
std::string sequence_id = j["sequence_id"].get<std::string>();
|
||||
CallAfter([this, sequence_id] {
|
||||
json ack_j;
|
||||
ack_j["command"] = "get_localhost_url";
|
||||
ack_j["response"]["base_url"] = std::string(LOCALHOST_URL) + std::to_string(LOCALHOST_PORT);
|
||||
int loopback_port = m_loopback_port > 0 ? m_loopback_port : LOCALHOST_PORT;
|
||||
ack_j["response"]["base_url"] = std::string(LOCALHOST_URL) + std::to_string(loopback_port);
|
||||
ack_j["response"]["result"] = "success";
|
||||
ack_j["sequence_id"] = sequence_id;
|
||||
wxString str_js = wxString::Format("window.postMessage(%s)", ack_j.dump());
|
||||
@@ -300,6 +365,8 @@ void ZUserLogin::OnScriptMessage(wxWebViewEvent &evt)
|
||||
BOOST_LOG_TRIVIAL(info) << "thirdparty_login: thirdparty_login";
|
||||
if (j["data"].contains("url")) {
|
||||
std::string jump_url = j["data"]["url"].get<std::string>();
|
||||
int loopback_port = m_loopback_port > 0 ? m_loopback_port : LOCALHOST_PORT;
|
||||
wxGetApp().start_http_server(loopback_port);
|
||||
CallAfter([this, jump_url] {
|
||||
wxString url = wxString::FromUTF8(jump_url);
|
||||
wxLaunchDefaultBrowser(url);
|
||||
|
||||
@@ -71,6 +71,7 @@ private:
|
||||
wxWebView *m_browser;
|
||||
|
||||
std::string m_AutotestToken;
|
||||
int m_loopback_port { 0 };
|
||||
|
||||
#if wxUSE_WEBVIEW_IE
|
||||
wxMenuItem *m_script_object_el;
|
||||
|
||||
864
src/slic3r/Utils/BBLCloudServiceAgent.cpp
Normal file
864
src/slic3r/Utils/BBLCloudServiceAgent.cpp
Normal file
@@ -0,0 +1,864 @@
|
||||
#include "BBLCloudServiceAgent.hpp"
|
||||
#include "BBLNetworkPlugin.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
BBLCloudServiceAgent::BBLCloudServiceAgent()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "BBLCloudServiceAgent: Constructor - using BBLNetworkPlugin singleton";
|
||||
}
|
||||
|
||||
BBLCloudServiceAgent::~BBLCloudServiceAgent() = default;
|
||||
|
||||
// ============================================================================
|
||||
// Lifecycle (merged from BBLAuthAgent)
|
||||
// ============================================================================
|
||||
|
||||
int BBLCloudServiceAgent::init_log()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_init_log();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::set_config_dir(std::string config_dir)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_config_dir();
|
||||
if (func && agent) {
|
||||
return func(agent, config_dir);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::set_cert_file(std::string folder, std::string filename)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_cert_file();
|
||||
if (func && agent) {
|
||||
return func(agent, folder, filename);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::set_country_code(std::string country_code)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_country_code();
|
||||
if (func && agent) {
|
||||
return func(agent, country_code);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::start()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_start();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// User Session Management (merged from BBLAuthAgent)
|
||||
// ============================================================================
|
||||
|
||||
int BBLCloudServiceAgent::change_user(std::string user_info)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_change_user();
|
||||
if (func && agent) {
|
||||
return func(agent, user_info);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool BBLCloudServiceAgent::is_user_login()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_is_user_login();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::user_logout(bool request)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_user_logout();
|
||||
if (func && agent) {
|
||||
return func(agent, request);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string BBLCloudServiceAgent::get_user_id()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_user_id();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string BBLCloudServiceAgent::get_user_name()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_user_name();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string BBLCloudServiceAgent::get_user_avatar()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_user_avatar();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string BBLCloudServiceAgent::get_user_nickname()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_user_nickanme();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Login UI Support (merged from BBLAuthAgent)
|
||||
// ============================================================================
|
||||
|
||||
std::string BBLCloudServiceAgent::build_login_cmd()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_build_login_cmd();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string BBLCloudServiceAgent::build_logout_cmd()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_build_logout_cmd();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string BBLCloudServiceAgent::build_login_info()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_build_login_info();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Token Access (merged from BBLAuthAgent)
|
||||
// ============================================================================
|
||||
|
||||
std::string BBLCloudServiceAgent::get_access_token() const
|
||||
{
|
||||
// BBL DLL manages tokens internally, not exposed via function pointer
|
||||
// Return empty string - BBL agents inject tokens automatically
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string BBLCloudServiceAgent::get_refresh_token() const
|
||||
{
|
||||
// BBL DLL manages tokens internally, not exposed via function pointer
|
||||
return "";
|
||||
}
|
||||
|
||||
bool BBLCloudServiceAgent::ensure_token_fresh(const std::string& reason)
|
||||
{
|
||||
// BBL DLL handles token refresh internally
|
||||
// Always return true assuming the DLL manages this
|
||||
(void)reason;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Auth Callbacks (merged from BBLAuthAgent)
|
||||
// ============================================================================
|
||||
|
||||
int BBLCloudServiceAgent::set_on_user_login_fn(OnUserLoginFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_user_login_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Server Connectivity
|
||||
// ============================================================================
|
||||
|
||||
std::string BBLCloudServiceAgent::get_cloud_service_host()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_bambulab_host();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string BBLCloudServiceAgent::get_cloud_login_url(const std::string& language)
|
||||
{
|
||||
std::string host_url = get_cloud_service_host();
|
||||
if (host_url.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (language.empty()) {
|
||||
return host_url + "/sign-in";
|
||||
}
|
||||
return host_url + "/" + language + "/sign-in";
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::connect_server()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_connect_server();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool BBLCloudServiceAgent::is_server_connected()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_is_server_connected();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::refresh_connection()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_refresh_connection();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::start_subscribe(std::string module)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_start_subscribe();
|
||||
if (func && agent) {
|
||||
return func(agent, module);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::stop_subscribe(std::string module)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_stop_subscribe();
|
||||
if (func && agent) {
|
||||
return func(agent, module);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::add_subscribe(std::vector<std::string> dev_list)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_add_subscribe();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_list);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::del_subscribe(std::vector<std::string> dev_list)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_del_subscribe();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_list);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void BBLCloudServiceAgent::enable_multi_machine(bool enable)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_enable_multi_machine();
|
||||
if (func && agent) {
|
||||
func(agent, enable);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Settings Synchronization
|
||||
// ============================================================================
|
||||
|
||||
int BBLCloudServiceAgent::get_user_presets(std::map<std::string, std::map<std::string, std::string>>* user_presets)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_user_presets();
|
||||
if (func && agent) {
|
||||
return func(agent, user_presets);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string BBLCloudServiceAgent::request_setting_id(std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_request_setting_id();
|
||||
if (func && agent) {
|
||||
return func(agent, name, values_map, http_code);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_put_setting();
|
||||
if (func && agent) {
|
||||
return func(agent, setting_id, name, values_map, http_code);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_setting_list(std::string bundle_version, ProgressFn pro_fn, WasCancelledFn cancel_fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_setting_list();
|
||||
if (func && agent) {
|
||||
return func(agent, bundle_version, pro_fn, cancel_fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_setting_list2(std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn, WasCancelledFn cancel_fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_setting_list2();
|
||||
if (func && agent) {
|
||||
return func(agent, bundle_version, chk_fn, pro_fn, cancel_fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::delete_setting(std::string setting_id)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_delete_setting();
|
||||
if (func && agent) {
|
||||
return func(agent, setting_id);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Cloud User Services
|
||||
// ============================================================================
|
||||
|
||||
int BBLCloudServiceAgent::get_my_message(int type, int after, int limit, unsigned int* http_code, std::string* http_body)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_my_message();
|
||||
if (func && agent) {
|
||||
return func(agent, type, after, limit, http_code, http_body);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::check_user_task_report(int* task_id, bool* printable)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_check_user_task_report();
|
||||
if (func && agent) {
|
||||
return func(agent, task_id, printable);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_user_print_info(unsigned int* http_code, std::string* http_body)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_user_print_info();
|
||||
if (func && agent) {
|
||||
return func(agent, http_code, http_body);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_user_tasks(TaskQueryParams params, std::string* http_body)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_user_tasks();
|
||||
if (func && agent) {
|
||||
return func(agent, params, http_body);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_printer_firmware(std::string dev_id, unsigned* http_code, std::string* http_body)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_printer_firmware();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_id, http_code, http_body);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_task_plate_index(std::string task_id, int* plate_index)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_task_plate_index();
|
||||
if (func && agent) {
|
||||
return func(agent, task_id, plate_index);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_user_info(int* identifier)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_user_info();
|
||||
if (func && agent) {
|
||||
return func(agent, identifier);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_subtask_info(std::string subtask_id, std::string* task_json, unsigned int* http_code, std::string* http_body)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_subtask_info();
|
||||
if (func && agent) {
|
||||
return func(agent, subtask_id, task_json, http_code, http_body);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_slice_info(std::string project_id, std::string profile_id, int plate_index, std::string* slice_json)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_slice_info();
|
||||
if (func && agent) {
|
||||
return func(agent, project_id, profile_id, plate_index, slice_json);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::query_bind_status(std::vector<std::string> query_list, unsigned int* http_code, std::string* http_body)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_query_bind_status();
|
||||
if (func && agent) {
|
||||
return func(agent, query_list, http_code, http_body);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::modify_printer_name(std::string dev_id, std::string dev_name)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_modify_printer_name();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_id, dev_name);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Model Mall & Publishing
|
||||
// ============================================================================
|
||||
|
||||
int BBLCloudServiceAgent::get_camera_url(std::string dev_id, std::function<void(std::string)> callback)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_camera_url();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_id, callback);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_design_staffpick(int offset, int limit, std::function<void(std::string)> callback)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_design_staffpick();
|
||||
if (func && agent) {
|
||||
return func(agent, offset, limit, callback);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::start_publish(PublishParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, std::string* out)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_start_publish();
|
||||
if (func && agent) {
|
||||
return func(agent, params, update_fn, cancel_fn, out);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_model_publish_url(std::string* url)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_model_publish_url();
|
||||
if (func && agent) {
|
||||
return func(agent, url);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_subtask(BBLModelTask* task, OnGetSubTaskFn getsub_fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_subtask();
|
||||
if (func && agent) {
|
||||
return func(agent, task, getsub_fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_model_mall_home_url(std::string* url)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_model_mall_home_url();
|
||||
if (func && agent) {
|
||||
return func(agent, url);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_model_mall_detail_url(std::string* url, std::string id)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_model_mall_detail_url();
|
||||
if (func && agent) {
|
||||
return func(agent, url, id);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_my_profile(std::string token, unsigned int* http_code, std::string* http_body)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_my_profile();
|
||||
if (func && agent) {
|
||||
return func(agent, token, http_code, http_body);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Analytics & Tracking
|
||||
// ============================================================================
|
||||
|
||||
int BBLCloudServiceAgent::track_enable(bool enable)
|
||||
{
|
||||
m_enable_track = enable;
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_track_enable();
|
||||
if (func && agent) {
|
||||
return func(agent, enable);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::track_remove_files()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_track_remove_files();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::track_event(std::string evt_key, std::string content)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_track_event();
|
||||
if (func && agent) {
|
||||
return func(agent, evt_key, content);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::track_header(std::string header)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_track_header();
|
||||
if (func && agent) {
|
||||
return func(agent, header);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::track_update_property(std::string name, std::string value, std::string type)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_track_update_property();
|
||||
if (func && agent) {
|
||||
return func(agent, name, value, type);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::track_get_property(std::string name, std::string& value, std::string type)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_track_get_property();
|
||||
if (func && agent) {
|
||||
return func(agent, name, value, type);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool BBLCloudServiceAgent::get_track_enable()
|
||||
{
|
||||
return m_enable_track;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Ratings & Reviews
|
||||
// ============================================================================
|
||||
|
||||
int BBLCloudServiceAgent::put_model_mall_rating(int design_id, int score, std::string content, std::vector<std::string> images, unsigned int& http_code, std::string& http_error)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_put_model_mall_rating();
|
||||
if (func && agent) {
|
||||
return func(agent, design_id, score, content, images, http_code, http_error);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_oss_config(std::string& config, std::string country_code, unsigned int& http_code, std::string& http_error)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_oss_config();
|
||||
if (func && agent) {
|
||||
return func(agent, config, country_code, http_code, http_error);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::put_rating_picture_oss(std::string& config, std::string& pic_oss_path, std::string model_id, int profile_id, unsigned int& http_code, std::string& http_error)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_put_rating_picture_oss();
|
||||
if (func && agent) {
|
||||
return func(agent, config, pic_oss_path, model_id, profile_id, http_code, http_error);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_model_mall_rating_result(int job_id, std::string& rating_result, unsigned int& http_code, std::string& http_error)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_model_mall_rating_result();
|
||||
if (func && agent) {
|
||||
return func(agent, job_id, rating_result, http_code, http_error);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Extra Features
|
||||
// ============================================================================
|
||||
|
||||
int BBLCloudServiceAgent::set_extra_http_header(std::map<std::string, std::string> extra_headers)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_extra_http_header();
|
||||
if (func && agent) {
|
||||
return func(agent, extra_headers);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string BBLCloudServiceAgent::get_studio_info_url()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_studio_info_url();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_mw_user_preference(std::function<void(std::string)> callback)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_mw_user_preference();
|
||||
if (func && agent) {
|
||||
return func(agent, callback);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::get_mw_user_4ulist(int seed, int limit, std::function<void(std::string)> callback)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_mw_user_4ulist();
|
||||
if (func && agent) {
|
||||
return func(agent, seed, limit, callback);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string BBLCloudServiceAgent::get_version()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto func = plugin.get_get_version();
|
||||
if (func) {
|
||||
return func();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Cloud Callbacks
|
||||
// ============================================================================
|
||||
|
||||
int BBLCloudServiceAgent::set_on_server_connected_fn(OnServerConnectedFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_server_connected_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::set_on_http_error_fn(OnHttpErrorFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_http_error_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::set_get_country_code_fn(GetCountryCodeFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_get_country_code_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLCloudServiceAgent::set_queue_on_main_fn(QueueOnMainFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_queue_on_main_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
136
src/slic3r/Utils/BBLCloudServiceAgent.hpp
Normal file
136
src/slic3r/Utils/BBLCloudServiceAgent.hpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#ifndef __BBL_CLOUD_SERVICE_AGENT_HPP__
|
||||
#define __BBL_CLOUD_SERVICE_AGENT_HPP__
|
||||
|
||||
#include "ICloudServiceAgent.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
/**
|
||||
* BBLCloudServiceAgent - BBL DLL wrapper implementation of ICloudServiceAgent.
|
||||
*
|
||||
* Delegates all cloud service and authentication operations to the proprietary
|
||||
* BBL network DLL through function pointers obtained from BBLNetworkPlugin singleton.
|
||||
* This class combines the functionality of the former BBLAuthAgent and BBLCloudServiceAgent.
|
||||
*/
|
||||
class BBLCloudServiceAgent : public ICloudServiceAgent {
|
||||
public:
|
||||
BBLCloudServiceAgent();
|
||||
~BBLCloudServiceAgent() override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Auth Methods
|
||||
// ========================================================================
|
||||
|
||||
// Lifecycle
|
||||
int init_log() override;
|
||||
int set_config_dir(std::string config_dir) override;
|
||||
int set_cert_file(std::string folder, std::string filename) override;
|
||||
int set_country_code(std::string country_code) override;
|
||||
int start() override;
|
||||
|
||||
// User Session Management
|
||||
int change_user(std::string user_info) override;
|
||||
bool is_user_login() override;
|
||||
int user_logout(bool request = false) override;
|
||||
std::string get_user_id() override;
|
||||
std::string get_user_name() override;
|
||||
std::string get_user_avatar() override;
|
||||
std::string get_user_nickname() override;
|
||||
|
||||
// Login UI Support
|
||||
std::string build_login_cmd() override;
|
||||
std::string build_logout_cmd() override;
|
||||
std::string build_login_info() override;
|
||||
|
||||
// Token Access (BBL manages tokens internally)
|
||||
std::string get_access_token() const override;
|
||||
std::string get_refresh_token() const override;
|
||||
bool ensure_token_fresh(const std::string& reason) override;
|
||||
|
||||
// Auth Callbacks
|
||||
int set_on_user_login_fn(OnUserLoginFn fn) override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Cloud Methods
|
||||
// ========================================================================
|
||||
|
||||
// Server Connectivity
|
||||
std::string get_cloud_service_host() override;
|
||||
std::string get_cloud_login_url(const std::string& language = "") override;
|
||||
int connect_server() override;
|
||||
bool is_server_connected() override;
|
||||
int refresh_connection() override;
|
||||
int start_subscribe(std::string module) override;
|
||||
int stop_subscribe(std::string module) override;
|
||||
int add_subscribe(std::vector<std::string> dev_list) override;
|
||||
int del_subscribe(std::vector<std::string> dev_list) override;
|
||||
void enable_multi_machine(bool enable) override;
|
||||
|
||||
// Settings Synchronization
|
||||
int get_user_presets(std::map<std::string, std::map<std::string, std::string>>* user_presets) override;
|
||||
std::string request_setting_id(std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
|
||||
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
|
||||
int get_setting_list(std::string bundle_version, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
|
||||
int get_setting_list2(std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
|
||||
int delete_setting(std::string setting_id) override;
|
||||
|
||||
// Cloud User Services
|
||||
int get_my_message(int type, int after, int limit, unsigned int* http_code, std::string* http_body) override;
|
||||
int check_user_task_report(int* task_id, bool* printable) override;
|
||||
int get_user_print_info(unsigned int* http_code, std::string* http_body) override;
|
||||
int get_user_tasks(TaskQueryParams params, std::string* http_body) override;
|
||||
int get_printer_firmware(std::string dev_id, unsigned* http_code, std::string* http_body) override;
|
||||
int get_task_plate_index(std::string task_id, int* plate_index) override;
|
||||
int get_user_info(int* identifier) override;
|
||||
int get_subtask_info(std::string subtask_id, std::string* task_json, unsigned int* http_code, std::string* http_body) override;
|
||||
int get_slice_info(std::string project_id, std::string profile_id, int plate_index, std::string* slice_json) override;
|
||||
int query_bind_status(std::vector<std::string> query_list, unsigned int* http_code, std::string* http_body) override;
|
||||
int modify_printer_name(std::string dev_id, std::string dev_name) override;
|
||||
|
||||
// Model Mall & Publishing
|
||||
int get_camera_url(std::string dev_id, std::function<void(std::string)> callback) override;
|
||||
int get_design_staffpick(int offset, int limit, std::function<void(std::string)> callback) override;
|
||||
int start_publish(PublishParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, std::string* out) override;
|
||||
int get_model_publish_url(std::string* url) override;
|
||||
int get_subtask(BBLModelTask* task, OnGetSubTaskFn getsub_fn) override;
|
||||
int get_model_mall_home_url(std::string* url) override;
|
||||
int get_model_mall_detail_url(std::string* url, std::string id) override;
|
||||
int get_my_profile(std::string token, unsigned int* http_code, std::string* http_body) override;
|
||||
|
||||
// Analytics & Tracking
|
||||
int track_enable(bool enable) override;
|
||||
int track_remove_files() override;
|
||||
int track_event(std::string evt_key, std::string content) override;
|
||||
int track_header(std::string header) override;
|
||||
int track_update_property(std::string name, std::string value, std::string type = "string") override;
|
||||
int track_get_property(std::string name, std::string& value, std::string type = "string") override;
|
||||
bool get_track_enable() override;
|
||||
|
||||
// Ratings & Reviews
|
||||
int put_model_mall_rating(int design_id, int score, std::string content, std::vector<std::string> images, unsigned int& http_code, std::string& http_error) override;
|
||||
int get_oss_config(std::string& config, std::string country_code, unsigned int& http_code, std::string& http_error) override;
|
||||
int put_rating_picture_oss(std::string& config, std::string& pic_oss_path, std::string model_id, int profile_id, unsigned int& http_code, std::string& http_error) override;
|
||||
int get_model_mall_rating_result(int job_id, std::string& rating_result, unsigned int& http_code, std::string& http_error) override;
|
||||
|
||||
// Extra Features
|
||||
int set_extra_http_header(std::map<std::string, std::string> extra_headers) override;
|
||||
std::string get_studio_info_url() override;
|
||||
int get_mw_user_preference(std::function<void(std::string)> callback) override;
|
||||
int get_mw_user_4ulist(int seed, int limit, std::function<void(std::string)> callback) override;
|
||||
std::string get_version() override;
|
||||
|
||||
// Cloud Callbacks
|
||||
int set_on_server_connected_fn(OnServerConnectedFn fn) override;
|
||||
int set_on_http_error_fn(OnHttpErrorFn fn) override;
|
||||
int set_get_country_code_fn(GetCountryCodeFn fn) override;
|
||||
int set_queue_on_main_fn(QueueOnMainFn fn) override;
|
||||
|
||||
private:
|
||||
bool m_enable_track{false};
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // __BBL_CLOUD_SERVICE_AGENT_HPP__
|
||||
823
src/slic3r/Utils/BBLNetworkPlugin.cpp
Normal file
823
src/slic3r/Utils/BBLNetworkPlugin.cpp
Normal file
@@ -0,0 +1,823 @@
|
||||
#include "BBLNetworkPlugin.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "slic3r/Utils/FileTransferUtils.hpp"
|
||||
|
||||
#if !defined(_MSC_VER) && !defined(_WIN32)
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
#define BAMBU_SOURCE_LIBRARY "BambuSource"
|
||||
|
||||
// ============================================================================
|
||||
// Singleton Implementation
|
||||
// ============================================================================
|
||||
|
||||
// Static pointer initialization (null by default, created on first access)
|
||||
BBLNetworkPlugin* BBLNetworkPlugin::s_instance = nullptr;
|
||||
|
||||
BBLNetworkPlugin& BBLNetworkPlugin::instance()
|
||||
{
|
||||
static std::once_flag flag;
|
||||
std::call_once(flag, [] {
|
||||
s_instance = new BBLNetworkPlugin();
|
||||
});
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
void BBLNetworkPlugin::shutdown()
|
||||
{
|
||||
// Note: Do not call instance() after shutdown() - the singleton is destroyed.
|
||||
if (s_instance) {
|
||||
delete s_instance;
|
||||
s_instance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BBLNetworkPlugin::BBLNetworkPlugin() = default;
|
||||
|
||||
BBLNetworkPlugin::~BBLNetworkPlugin()
|
||||
{
|
||||
destroy_agent();
|
||||
unload();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Module Lifecycle
|
||||
// ============================================================================
|
||||
|
||||
int BBLNetworkPlugin::initialize(bool using_backup, const std::string& version)
|
||||
{
|
||||
clear_load_error();
|
||||
|
||||
std::string library;
|
||||
std::string data_dir_str = data_dir();
|
||||
boost::filesystem::path data_dir_path(data_dir_str);
|
||||
auto plugin_folder = data_dir_path / "plugins";
|
||||
|
||||
if (using_backup) {
|
||||
plugin_folder = plugin_folder / "backup";
|
||||
}
|
||||
|
||||
if (version.empty()) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": version is required but not provided";
|
||||
set_load_error(
|
||||
"Network library version not specified",
|
||||
"A version must be specified to load the network library",
|
||||
""
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Auto-migration: If loading legacy version and versioned library doesn't exist,
|
||||
// but unversioned legacy library does exist, rename it to versioned format
|
||||
if (version == BAMBU_NETWORK_AGENT_VERSION_LEGACY) {
|
||||
boost::filesystem::path versioned_path;
|
||||
boost::filesystem::path legacy_path;
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
versioned_path = plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".dll");
|
||||
legacy_path = plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + ".dll");
|
||||
#elif defined(__WXMAC__)
|
||||
versioned_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".dylib");
|
||||
legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".dylib");
|
||||
#else
|
||||
versioned_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".so");
|
||||
legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".so");
|
||||
#endif
|
||||
if (!boost::filesystem::exists(versioned_path) && boost::filesystem::exists(legacy_path)) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": auto-migrating unversioned legacy library to versioned format";
|
||||
|
||||
try {
|
||||
boost::filesystem::rename(legacy_path, versioned_path);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": successfully renamed " << legacy_path.string() << " to "
|
||||
<< versioned_path.string();
|
||||
} catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": failed to rename legacy library: " << e.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load versioned library
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
library = plugin_folder.string() + "\\" + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".dll";
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": loading versioned library at " << library;
|
||||
#else
|
||||
#if defined(__WXMAC__)
|
||||
std::string lib_ext = ".dylib";
|
||||
#else
|
||||
std::string lib_ext = ".so";
|
||||
#endif
|
||||
library = plugin_folder.string() + "/" + std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + lib_ext;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": loading versioned library at " << library;
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
wchar_t lib_wstr[256];
|
||||
memset(lib_wstr, 0, sizeof(lib_wstr));
|
||||
::MultiByteToWideChar(CP_UTF8, NULL, library.c_str(), strlen(library.c_str())+1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0]));
|
||||
m_networking_module = LoadLibrary(lib_wstr);
|
||||
if (!m_networking_module) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": versioned library not found, trying current directory";
|
||||
std::string library_path = get_libpath_in_current_directory(std::string(BAMBU_NETWORK_LIBRARY));
|
||||
if (library_path.empty()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", can not get path in current directory for %1%") % BAMBU_NETWORK_LIBRARY;
|
||||
set_load_error(
|
||||
"Network library not found",
|
||||
"Could not locate versioned library: " + library,
|
||||
library
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", current path %1%")%library_path;
|
||||
memset(lib_wstr, 0, sizeof(lib_wstr));
|
||||
::MultiByteToWideChar(CP_UTF8, NULL, library_path.c_str(), strlen(library_path.c_str())+1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0]));
|
||||
m_networking_module = LoadLibrary(lib_wstr);
|
||||
}
|
||||
#else
|
||||
m_networking_module = dlopen(library.c_str(), RTLD_LAZY);
|
||||
if (!m_networking_module) {
|
||||
char* dll_error = dlerror();
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": dlopen failed: " << (dll_error ? dll_error : "unknown error");
|
||||
set_load_error(
|
||||
"Failed to load network library",
|
||||
dll_error ? std::string(dll_error) : "Unknown dlopen error",
|
||||
library
|
||||
);
|
||||
}
|
||||
printf("after dlopen, network_module is %p\n", m_networking_module);
|
||||
#endif
|
||||
|
||||
if (!m_networking_module) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", can not Load Library for %1%")%library;
|
||||
if (!m_load_error.has_error) {
|
||||
set_load_error(
|
||||
"Network library failed to load",
|
||||
"LoadLibrary/dlopen returned null",
|
||||
library
|
||||
);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", successfully loaded library %1%, module %2%")%library %m_networking_module;
|
||||
|
||||
// Load file transfer interface
|
||||
InitFTModule(m_networking_module);
|
||||
|
||||
// Load all function pointers
|
||||
load_all_function_pointers();
|
||||
|
||||
if (m_get_version) {
|
||||
std::string ver = m_get_version();
|
||||
printf("network plugin version: %s\n", ver.c_str());
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": network plugin version = " << ver;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BBLNetworkPlugin::unload()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", network module %1%")%m_networking_module;
|
||||
|
||||
UnloadFTModule();
|
||||
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
if (m_networking_module) {
|
||||
FreeLibrary(m_networking_module);
|
||||
m_networking_module = NULL;
|
||||
}
|
||||
if (m_source_module) {
|
||||
FreeLibrary(m_source_module);
|
||||
m_source_module = NULL;
|
||||
}
|
||||
#else
|
||||
if (m_networking_module) {
|
||||
dlclose(m_networking_module);
|
||||
m_networking_module = NULL;
|
||||
}
|
||||
if (m_source_module) {
|
||||
dlclose(m_source_module);
|
||||
m_source_module = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
clear_all_function_pointers();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BBLNetworkPlugin::is_loaded() const
|
||||
{
|
||||
return m_networking_module != nullptr;
|
||||
}
|
||||
|
||||
std::string BBLNetworkPlugin::get_version() const
|
||||
{
|
||||
bool consistent = true;
|
||||
// Check the debug consistent first
|
||||
if (m_check_debug_consistent) {
|
||||
#if defined(NDEBUG)
|
||||
consistent = m_check_debug_consistent(false);
|
||||
#else
|
||||
consistent = m_check_debug_consistent(true);
|
||||
#endif
|
||||
}
|
||||
if (!consistent) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", inconsistent library, return 00.00.00.00!");
|
||||
return "00.00.00.00";
|
||||
}
|
||||
if (m_get_version) {
|
||||
return m_get_version();
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", get_version not supported, return 00.00.00.00!");
|
||||
return "00.00.00.00";
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Agent Lifecycle
|
||||
// ============================================================================
|
||||
|
||||
void* BBLNetworkPlugin::create_agent(const std::string& log_dir)
|
||||
{
|
||||
if (m_agent) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": agent already exists";
|
||||
return m_agent;
|
||||
}
|
||||
|
||||
if (m_create_agent) {
|
||||
m_agent = m_create_agent(log_dir);
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", agent=%1%, create_agent=%2%, log_dir=%3%")
|
||||
% m_agent % (m_create_agent ? "yes" : "no") % log_dir;
|
||||
|
||||
return m_agent;
|
||||
}
|
||||
|
||||
int BBLNetworkPlugin::destroy_agent()
|
||||
{
|
||||
int ret = 0;
|
||||
if (m_agent && m_destroy_agent) {
|
||||
ret = m_destroy_agent(m_agent);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", agent=%1%, destroy_agent=%2%, ret=%3%")
|
||||
% m_agent % (m_destroy_agent ? "yes" : "no") % ret;
|
||||
m_agent = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// DLL Module Accessors
|
||||
// ============================================================================
|
||||
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
HMODULE BBLNetworkPlugin::get_source_module()
|
||||
#else
|
||||
void* BBLNetworkPlugin::get_source_module()
|
||||
#endif
|
||||
{
|
||||
if ((m_source_module) || (!m_networking_module))
|
||||
return m_source_module;
|
||||
|
||||
std::string library;
|
||||
std::string data_dir_str = data_dir();
|
||||
boost::filesystem::path data_dir_path(data_dir_str);
|
||||
auto plugin_folder = data_dir_path / "plugins";
|
||||
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
wchar_t lib_wstr[128];
|
||||
|
||||
library = plugin_folder.string() + "/" + std::string(BAMBU_SOURCE_LIBRARY) + ".dll";
|
||||
memset(lib_wstr, 0, sizeof(lib_wstr));
|
||||
::MultiByteToWideChar(CP_UTF8, NULL, library.c_str(), strlen(library.c_str())+1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0]));
|
||||
m_source_module = LoadLibrary(lib_wstr);
|
||||
if (!m_source_module) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", try load BambuSource directly from current directory");
|
||||
std::string library_path = get_libpath_in_current_directory(std::string(BAMBU_SOURCE_LIBRARY));
|
||||
if (library_path.empty()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", can not get path in current directory for %1%") % BAMBU_SOURCE_LIBRARY;
|
||||
return m_source_module;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", current path %1%")%library_path;
|
||||
memset(lib_wstr, 0, sizeof(lib_wstr));
|
||||
::MultiByteToWideChar(CP_UTF8, NULL, library_path.c_str(), strlen(library_path.c_str()) + 1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0]));
|
||||
m_source_module = LoadLibrary(lib_wstr);
|
||||
}
|
||||
#else
|
||||
#if defined(__WXMAC__)
|
||||
library = plugin_folder.string() + "/" + std::string("lib") + std::string(BAMBU_SOURCE_LIBRARY) + ".dylib";
|
||||
#else
|
||||
library = plugin_folder.string() + "/" + std::string("lib") + std::string(BAMBU_SOURCE_LIBRARY) + ".so";
|
||||
#endif
|
||||
m_source_module = dlopen(library.c_str(), RTLD_LAZY);
|
||||
#endif
|
||||
|
||||
return m_source_module;
|
||||
}
|
||||
|
||||
void* BBLNetworkPlugin::get_function(const char* name)
|
||||
{
|
||||
void* function = nullptr;
|
||||
|
||||
if (!m_networking_module)
|
||||
return function;
|
||||
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
function = GetProcAddress(m_networking_module, name);
|
||||
#else
|
||||
function = dlsym(m_networking_module, name);
|
||||
#endif
|
||||
|
||||
if (!function) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", can not find function %1%")%name;
|
||||
}
|
||||
return function;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Utility Methods
|
||||
// ============================================================================
|
||||
|
||||
std::string BBLNetworkPlugin::get_libpath_in_current_directory(const std::string& library_name)
|
||||
{
|
||||
std::string lib_path;
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
wchar_t file_name[512];
|
||||
DWORD ret = GetModuleFileNameW(NULL, file_name, 512);
|
||||
if (!ret) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", GetModuleFileNameW return error, can not Load Library for %1%") % library_name;
|
||||
return lib_path;
|
||||
}
|
||||
int size_needed = ::WideCharToMultiByte(0, 0, file_name, wcslen(file_name), nullptr, 0, nullptr, nullptr);
|
||||
std::string file_name_string(size_needed, 0);
|
||||
::WideCharToMultiByte(0, 0, file_name, wcslen(file_name), file_name_string.data(), size_needed, nullptr, nullptr);
|
||||
|
||||
std::size_t found = file_name_string.find("orca-slicer.exe");
|
||||
if (found == (file_name_string.size() - 16)) {
|
||||
lib_path = library_name + ".dll";
|
||||
lib_path = file_name_string.replace(found, 16, lib_path);
|
||||
}
|
||||
#else
|
||||
(void)library_name;
|
||||
#endif
|
||||
return lib_path;
|
||||
}
|
||||
|
||||
std::string BBLNetworkPlugin::get_versioned_library_path(const std::string& version)
|
||||
{
|
||||
std::string data_dir_str = data_dir();
|
||||
boost::filesystem::path data_dir_path(data_dir_str);
|
||||
auto plugin_folder = data_dir_path / "plugins";
|
||||
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
return (plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".dll")).string();
|
||||
#elif defined(__WXMAC__)
|
||||
return (plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".dylib")).string();
|
||||
#else
|
||||
return (plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_" + version + ".so")).string();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool BBLNetworkPlugin::versioned_library_exists(const std::string& version)
|
||||
{
|
||||
if (version.empty()) return false;
|
||||
std::string path = get_versioned_library_path(version);
|
||||
|
||||
if (boost::filesystem::exists(path)) return true;
|
||||
|
||||
if (version == BAMBU_NETWORK_AGENT_VERSION_LEGACY) {
|
||||
return legacy_library_exists();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BBLNetworkPlugin::legacy_library_exists()
|
||||
{
|
||||
std::string data_dir_str = data_dir();
|
||||
boost::filesystem::path data_dir_path(data_dir_str);
|
||||
auto plugin_folder = data_dir_path / "plugins";
|
||||
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
auto legacy_path = plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + ".dll");
|
||||
#elif defined(__WXMAC__)
|
||||
auto legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".dylib");
|
||||
#else
|
||||
auto legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".so");
|
||||
#endif
|
||||
return boost::filesystem::exists(legacy_path);
|
||||
}
|
||||
|
||||
void BBLNetworkPlugin::remove_legacy_library()
|
||||
{
|
||||
std::string data_dir_str = data_dir();
|
||||
boost::filesystem::path data_dir_path(data_dir_str);
|
||||
auto plugin_folder = data_dir_path / "plugins";
|
||||
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
auto legacy_path = plugin_folder / (std::string(BAMBU_NETWORK_LIBRARY) + ".dll");
|
||||
#elif defined(__WXMAC__)
|
||||
auto legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".dylib");
|
||||
#else
|
||||
auto legacy_path = plugin_folder / (std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + ".so");
|
||||
#endif
|
||||
|
||||
if (boost::filesystem::exists(legacy_path)) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": removing legacy library at " << legacy_path.string();
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::remove(legacy_path, ec);
|
||||
if (ec) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": failed to remove legacy library: " << ec.message();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> BBLNetworkPlugin::scan_plugin_versions()
|
||||
{
|
||||
std::vector<std::string> discovered_versions;
|
||||
std::string data_dir_str = data_dir();
|
||||
boost::filesystem::path plugin_folder = boost::filesystem::path(data_dir_str) / "plugins";
|
||||
|
||||
if (!boost::filesystem::is_directory(plugin_folder)) {
|
||||
return discovered_versions;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
std::string prefix = std::string(BAMBU_NETWORK_LIBRARY) + "_";
|
||||
std::string extension = ".dll";
|
||||
#elif defined(__WXMAC__)
|
||||
std::string prefix = std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_";
|
||||
std::string extension = ".dylib";
|
||||
#else
|
||||
std::string prefix = std::string("lib") + std::string(BAMBU_NETWORK_LIBRARY) + "_";
|
||||
std::string extension = ".so";
|
||||
#endif
|
||||
|
||||
boost::system::error_code ec;
|
||||
for (auto& entry : boost::filesystem::directory_iterator(plugin_folder, ec)) {
|
||||
if (ec) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": error iterating directory: " << ec.message();
|
||||
break;
|
||||
}
|
||||
if (!boost::filesystem::is_regular_file(entry.status()))
|
||||
continue;
|
||||
|
||||
std::string filename = entry.path().filename().string();
|
||||
|
||||
if (filename.rfind(prefix, 0) != 0)
|
||||
continue;
|
||||
if (filename.size() <= extension.size() ||
|
||||
filename.compare(filename.size() - extension.size(), extension.size(), extension) != 0)
|
||||
continue;
|
||||
|
||||
std::string version = filename.substr(prefix.size(),
|
||||
filename.size() - prefix.size() - extension.size());
|
||||
discovered_versions.push_back(version);
|
||||
}
|
||||
|
||||
return discovered_versions;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Error Handling
|
||||
// ============================================================================
|
||||
|
||||
void BBLNetworkPlugin::clear_load_error()
|
||||
{
|
||||
m_load_error = NetworkLibraryLoadError{};
|
||||
}
|
||||
|
||||
void BBLNetworkPlugin::set_load_error(const std::string& message,
|
||||
const std::string& technical_details,
|
||||
const std::string& attempted_path)
|
||||
{
|
||||
m_load_error.has_error = true;
|
||||
m_load_error.message = message;
|
||||
m_load_error.technical_details = technical_details;
|
||||
m_load_error.attempted_path = attempted_path;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Legacy Helper
|
||||
// ============================================================================
|
||||
|
||||
PrintParams_Legacy BBLNetworkPlugin::as_legacy(PrintParams& param)
|
||||
{
|
||||
PrintParams_Legacy l;
|
||||
|
||||
l.dev_id = std::move(param.dev_id);
|
||||
l.task_name = std::move(param.task_name);
|
||||
l.project_name = std::move(param.project_name);
|
||||
l.preset_name = std::move(param.preset_name);
|
||||
l.filename = std::move(param.filename);
|
||||
l.config_filename = std::move(param.config_filename);
|
||||
l.plate_index = param.plate_index;
|
||||
l.ftp_folder = std::move(param.ftp_folder);
|
||||
l.ftp_file = std::move(param.ftp_file);
|
||||
l.ftp_file_md5 = std::move(param.ftp_file_md5);
|
||||
l.ams_mapping = std::move(param.ams_mapping);
|
||||
l.ams_mapping_info = std::move(param.ams_mapping_info);
|
||||
l.connection_type = std::move(param.connection_type);
|
||||
l.comments = std::move(param.comments);
|
||||
l.origin_profile_id = param.origin_profile_id;
|
||||
l.stl_design_id = param.stl_design_id;
|
||||
l.origin_model_id = std::move(param.origin_model_id);
|
||||
l.print_type = std::move(param.print_type);
|
||||
l.dst_file = std::move(param.dst_file);
|
||||
l.dev_name = std::move(param.dev_name);
|
||||
l.dev_ip = std::move(param.dev_ip);
|
||||
l.use_ssl_for_ftp = param.use_ssl_for_ftp;
|
||||
l.use_ssl_for_mqtt = param.use_ssl_for_mqtt;
|
||||
l.username = std::move(param.username);
|
||||
l.password = std::move(param.password);
|
||||
l.task_bed_leveling = param.task_bed_leveling;
|
||||
l.task_flow_cali = param.task_flow_cali;
|
||||
l.task_vibration_cali = param.task_vibration_cali;
|
||||
l.task_layer_inspect = param.task_layer_inspect;
|
||||
l.task_record_timelapse = param.task_record_timelapse;
|
||||
l.task_use_ams = param.task_use_ams;
|
||||
l.task_bed_type = std::move(param.task_bed_type);
|
||||
l.extra_options = std::move(param.extra_options);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Function Pointer Loading
|
||||
// ============================================================================
|
||||
|
||||
void BBLNetworkPlugin::load_all_function_pointers()
|
||||
{
|
||||
m_check_debug_consistent = reinterpret_cast<func_check_debug_consistent>(get_function("bambu_network_check_debug_consistent"));
|
||||
m_get_version = reinterpret_cast<func_get_version>(get_function("bambu_network_get_version"));
|
||||
m_create_agent = reinterpret_cast<func_create_agent>(get_function("bambu_network_create_agent"));
|
||||
m_destroy_agent = reinterpret_cast<func_destroy_agent>(get_function("bambu_network_destroy_agent"));
|
||||
m_init_log = reinterpret_cast<func_init_log>(get_function("bambu_network_init_log"));
|
||||
m_set_config_dir = reinterpret_cast<func_set_config_dir>(get_function("bambu_network_set_config_dir"));
|
||||
m_set_cert_file = reinterpret_cast<func_set_cert_file>(get_function("bambu_network_set_cert_file"));
|
||||
m_set_country_code = reinterpret_cast<func_set_country_code>(get_function("bambu_network_set_country_code"));
|
||||
m_start = reinterpret_cast<func_start>(get_function("bambu_network_start"));
|
||||
m_set_on_ssdp_msg_fn = reinterpret_cast<func_set_on_ssdp_msg_fn>(get_function("bambu_network_set_on_ssdp_msg_fn"));
|
||||
m_set_on_user_login_fn = reinterpret_cast<func_set_on_user_login_fn>(get_function("bambu_network_set_on_user_login_fn"));
|
||||
m_set_on_printer_connected_fn = reinterpret_cast<func_set_on_printer_connected_fn>(get_function("bambu_network_set_on_printer_connected_fn"));
|
||||
m_set_on_server_connected_fn = reinterpret_cast<func_set_on_server_connected_fn>(get_function("bambu_network_set_on_server_connected_fn"));
|
||||
m_set_on_http_error_fn = reinterpret_cast<func_set_on_http_error_fn>(get_function("bambu_network_set_on_http_error_fn"));
|
||||
m_set_get_country_code_fn = reinterpret_cast<func_set_get_country_code_fn>(get_function("bambu_network_set_get_country_code_fn"));
|
||||
m_set_on_subscribe_failure_fn = reinterpret_cast<func_set_on_subscribe_failure_fn>(get_function("bambu_network_set_on_subscribe_failure_fn"));
|
||||
m_set_on_message_fn = reinterpret_cast<func_set_on_message_fn>(get_function("bambu_network_set_on_message_fn"));
|
||||
m_set_on_user_message_fn = reinterpret_cast<func_set_on_user_message_fn>(get_function("bambu_network_set_on_user_message_fn"));
|
||||
m_set_on_local_connect_fn = reinterpret_cast<func_set_on_local_connect_fn>(get_function("bambu_network_set_on_local_connect_fn"));
|
||||
m_set_on_local_message_fn = reinterpret_cast<func_set_on_local_message_fn>(get_function("bambu_network_set_on_local_message_fn"));
|
||||
m_set_queue_on_main_fn = reinterpret_cast<func_set_queue_on_main_fn>(get_function("bambu_network_set_queue_on_main_fn"));
|
||||
m_connect_server = reinterpret_cast<func_connect_server>(get_function("bambu_network_connect_server"));
|
||||
m_is_server_connected = reinterpret_cast<func_is_server_connected>(get_function("bambu_network_is_server_connected"));
|
||||
m_refresh_connection = reinterpret_cast<func_refresh_connection>(get_function("bambu_network_refresh_connection"));
|
||||
m_start_subscribe = reinterpret_cast<func_start_subscribe>(get_function("bambu_network_start_subscribe"));
|
||||
m_stop_subscribe = reinterpret_cast<func_stop_subscribe>(get_function("bambu_network_stop_subscribe"));
|
||||
m_add_subscribe = reinterpret_cast<func_add_subscribe>(get_function("bambu_network_add_subscribe"));
|
||||
m_del_subscribe = reinterpret_cast<func_del_subscribe>(get_function("bambu_network_del_subscribe"));
|
||||
m_enable_multi_machine = reinterpret_cast<func_enable_multi_machine>(get_function("bambu_network_enable_multi_machine"));
|
||||
m_send_message = reinterpret_cast<func_send_message>(get_function("bambu_network_send_message"));
|
||||
m_connect_printer = reinterpret_cast<func_connect_printer>(get_function("bambu_network_connect_printer"));
|
||||
m_disconnect_printer = reinterpret_cast<func_disconnect_printer>(get_function("bambu_network_disconnect_printer"));
|
||||
m_send_message_to_printer = reinterpret_cast<func_send_message_to_printer>(get_function("bambu_network_send_message_to_printer"));
|
||||
m_check_cert = reinterpret_cast<func_check_cert>(get_function("bambu_network_update_cert"));
|
||||
m_install_device_cert = reinterpret_cast<func_install_device_cert>(get_function("bambu_network_install_device_cert"));
|
||||
m_start_discovery = reinterpret_cast<func_start_discovery>(get_function("bambu_network_start_discovery"));
|
||||
m_change_user = reinterpret_cast<func_change_user>(get_function("bambu_network_change_user"));
|
||||
m_is_user_login = reinterpret_cast<func_is_user_login>(get_function("bambu_network_is_user_login"));
|
||||
m_user_logout = reinterpret_cast<func_user_logout>(get_function("bambu_network_user_logout"));
|
||||
m_get_user_id = reinterpret_cast<func_get_user_id>(get_function("bambu_network_get_user_id"));
|
||||
m_get_user_name = reinterpret_cast<func_get_user_name>(get_function("bambu_network_get_user_name"));
|
||||
m_get_user_avatar = reinterpret_cast<func_get_user_avatar>(get_function("bambu_network_get_user_avatar"));
|
||||
m_get_user_nickanme = reinterpret_cast<func_get_user_nickanme>(get_function("bambu_network_get_user_nickanme"));
|
||||
m_build_login_cmd = reinterpret_cast<func_build_login_cmd>(get_function("bambu_network_build_login_cmd"));
|
||||
m_build_logout_cmd = reinterpret_cast<func_build_logout_cmd>(get_function("bambu_network_build_logout_cmd"));
|
||||
m_build_login_info = reinterpret_cast<func_build_login_info>(get_function("bambu_network_build_login_info"));
|
||||
m_ping_bind = reinterpret_cast<func_ping_bind>(get_function("bambu_network_ping_bind"));
|
||||
m_bind_detect = reinterpret_cast<func_bind_detect>(get_function("bambu_network_bind_detect"));
|
||||
m_set_server_callback = reinterpret_cast<func_set_server_callback>(get_function("bambu_network_set_server_callback"));
|
||||
m_bind = reinterpret_cast<func_bind>(get_function("bambu_network_bind"));
|
||||
m_unbind = reinterpret_cast<func_unbind>(get_function("bambu_network_unbind"));
|
||||
m_get_bambulab_host = reinterpret_cast<func_get_bambulab_host>(get_function("bambu_network_get_bambulab_host"));
|
||||
m_get_user_selected_machine = reinterpret_cast<func_get_user_selected_machine>(get_function("bambu_network_get_user_selected_machine"));
|
||||
m_set_user_selected_machine = reinterpret_cast<func_set_user_selected_machine>(get_function("bambu_network_set_user_selected_machine"));
|
||||
m_start_print = reinterpret_cast<func_start_print>(get_function("bambu_network_start_print"));
|
||||
m_start_local_print_with_record = reinterpret_cast<func_start_local_print_with_record>(get_function("bambu_network_start_local_print_with_record"));
|
||||
m_start_send_gcode_to_sdcard = reinterpret_cast<func_start_send_gcode_to_sdcard>(get_function("bambu_network_start_send_gcode_to_sdcard"));
|
||||
m_start_local_print = reinterpret_cast<func_start_local_print>(get_function("bambu_network_start_local_print"));
|
||||
m_start_sdcard_print = reinterpret_cast<func_start_sdcard_print>(get_function("bambu_network_start_sdcard_print"));
|
||||
m_get_user_presets = reinterpret_cast<func_get_user_presets>(get_function("bambu_network_get_user_presets"));
|
||||
m_request_setting_id = reinterpret_cast<func_request_setting_id>(get_function("bambu_network_request_setting_id"));
|
||||
m_put_setting = reinterpret_cast<func_put_setting>(get_function("bambu_network_put_setting"));
|
||||
m_get_setting_list = reinterpret_cast<func_get_setting_list>(get_function("bambu_network_get_setting_list"));
|
||||
m_get_setting_list2 = reinterpret_cast<func_get_setting_list2>(get_function("bambu_network_get_setting_list2"));
|
||||
m_delete_setting = reinterpret_cast<func_delete_setting>(get_function("bambu_network_delete_setting"));
|
||||
m_get_studio_info_url = reinterpret_cast<func_get_studio_info_url>(get_function("bambu_network_get_studio_info_url"));
|
||||
m_set_extra_http_header = reinterpret_cast<func_set_extra_http_header>(get_function("bambu_network_set_extra_http_header"));
|
||||
m_get_my_message = reinterpret_cast<func_get_my_message>(get_function("bambu_network_get_my_message"));
|
||||
m_check_user_task_report = reinterpret_cast<func_check_user_task_report>(get_function("bambu_network_check_user_task_report"));
|
||||
m_get_user_print_info = reinterpret_cast<func_get_user_print_info>(get_function("bambu_network_get_user_print_info"));
|
||||
m_get_user_tasks = reinterpret_cast<func_get_user_tasks>(get_function("bambu_network_get_user_tasks"));
|
||||
m_get_printer_firmware = reinterpret_cast<func_get_printer_firmware>(get_function("bambu_network_get_printer_firmware"));
|
||||
m_get_task_plate_index = reinterpret_cast<func_get_task_plate_index>(get_function("bambu_network_get_task_plate_index"));
|
||||
m_get_user_info = reinterpret_cast<func_get_user_info>(get_function("bambu_network_get_user_info"));
|
||||
m_request_bind_ticket = reinterpret_cast<func_request_bind_ticket>(get_function("bambu_network_request_bind_ticket"));
|
||||
m_get_subtask_info = reinterpret_cast<func_get_subtask_info>(get_function("bambu_network_get_subtask_info"));
|
||||
m_get_slice_info = reinterpret_cast<func_get_slice_info>(get_function("bambu_network_get_slice_info"));
|
||||
m_query_bind_status = reinterpret_cast<func_query_bind_status>(get_function("bambu_network_query_bind_status"));
|
||||
m_modify_printer_name = reinterpret_cast<func_modify_printer_name>(get_function("bambu_network_modify_printer_name"));
|
||||
m_get_camera_url = reinterpret_cast<func_get_camera_url>(get_function("bambu_network_get_camera_url"));
|
||||
m_get_design_staffpick = reinterpret_cast<func_get_design_staffpick>(get_function("bambu_network_get_design_staffpick"));
|
||||
m_start_publish = reinterpret_cast<func_start_pubilsh>(get_function("bambu_network_start_publish"));
|
||||
m_get_model_publish_url = reinterpret_cast<func_get_model_publish_url>(get_function("bambu_network_get_model_publish_url"));
|
||||
m_get_subtask = reinterpret_cast<func_get_subtask>(get_function("bambu_network_get_subtask"));
|
||||
m_get_model_mall_home_url = reinterpret_cast<func_get_model_mall_home_url>(get_function("bambu_network_get_model_mall_home_url"));
|
||||
m_get_model_mall_detail_url = reinterpret_cast<func_get_model_mall_detail_url>(get_function("bambu_network_get_model_mall_detail_url"));
|
||||
m_get_my_profile = reinterpret_cast<func_get_my_profile>(get_function("bambu_network_get_my_profile"));
|
||||
m_track_enable = reinterpret_cast<func_track_enable>(get_function("bambu_network_track_enable"));
|
||||
m_track_remove_files = reinterpret_cast<func_track_remove_files>(get_function("bambu_network_track_remove_files"));
|
||||
m_track_event = reinterpret_cast<func_track_event>(get_function("bambu_network_track_event"));
|
||||
m_track_header = reinterpret_cast<func_track_header>(get_function("bambu_network_track_header"));
|
||||
m_track_update_property = reinterpret_cast<func_track_update_property>(get_function("bambu_network_track_update_property"));
|
||||
m_track_get_property = reinterpret_cast<func_track_get_property>(get_function("bambu_network_track_get_property"));
|
||||
m_put_model_mall_rating = reinterpret_cast<func_put_model_mall_rating_url>(get_function("bambu_network_put_model_mall_rating"));
|
||||
m_get_oss_config = reinterpret_cast<func_get_oss_config>(get_function("bambu_network_get_oss_config"));
|
||||
m_put_rating_picture_oss = reinterpret_cast<func_put_rating_picture_oss>(get_function("bambu_network_put_rating_picture_oss"));
|
||||
m_get_model_mall_rating_result = reinterpret_cast<func_get_model_mall_rating_result>(get_function("bambu_network_get_model_mall_rating"));
|
||||
m_get_mw_user_preference = reinterpret_cast<func_get_mw_user_preference>(get_function("bambu_network_get_mw_user_preference"));
|
||||
m_get_mw_user_4ulist = reinterpret_cast<func_get_mw_user_4ulist>(get_function("bambu_network_get_mw_user_4ulist"));
|
||||
}
|
||||
|
||||
void BBLNetworkPlugin::clear_all_function_pointers()
|
||||
{
|
||||
m_check_debug_consistent = nullptr;
|
||||
m_get_version = nullptr;
|
||||
m_create_agent = nullptr;
|
||||
m_destroy_agent = nullptr;
|
||||
m_init_log = nullptr;
|
||||
m_set_config_dir = nullptr;
|
||||
m_set_cert_file = nullptr;
|
||||
m_set_country_code = nullptr;
|
||||
m_start = nullptr;
|
||||
m_set_on_ssdp_msg_fn = nullptr;
|
||||
m_set_on_user_login_fn = nullptr;
|
||||
m_set_on_printer_connected_fn = nullptr;
|
||||
m_set_on_server_connected_fn = nullptr;
|
||||
m_set_on_http_error_fn = nullptr;
|
||||
m_set_get_country_code_fn = nullptr;
|
||||
m_set_on_subscribe_failure_fn = nullptr;
|
||||
m_set_on_message_fn = nullptr;
|
||||
m_set_on_user_message_fn = nullptr;
|
||||
m_set_on_local_connect_fn = nullptr;
|
||||
m_set_on_local_message_fn = nullptr;
|
||||
m_set_queue_on_main_fn = nullptr;
|
||||
m_connect_server = nullptr;
|
||||
m_is_server_connected = nullptr;
|
||||
m_refresh_connection = nullptr;
|
||||
m_start_subscribe = nullptr;
|
||||
m_stop_subscribe = nullptr;
|
||||
m_add_subscribe = nullptr;
|
||||
m_del_subscribe = nullptr;
|
||||
m_enable_multi_machine = nullptr;
|
||||
m_send_message = nullptr;
|
||||
m_connect_printer = nullptr;
|
||||
m_disconnect_printer = nullptr;
|
||||
m_send_message_to_printer = nullptr;
|
||||
m_check_cert = nullptr;
|
||||
m_install_device_cert = nullptr;
|
||||
m_start_discovery = nullptr;
|
||||
m_change_user = nullptr;
|
||||
m_is_user_login = nullptr;
|
||||
m_user_logout = nullptr;
|
||||
m_get_user_id = nullptr;
|
||||
m_get_user_name = nullptr;
|
||||
m_get_user_avatar = nullptr;
|
||||
m_get_user_nickanme = nullptr;
|
||||
m_build_login_cmd = nullptr;
|
||||
m_build_logout_cmd = nullptr;
|
||||
m_build_login_info = nullptr;
|
||||
m_ping_bind = nullptr;
|
||||
m_bind_detect = nullptr;
|
||||
m_set_server_callback = nullptr;
|
||||
m_bind = nullptr;
|
||||
m_unbind = nullptr;
|
||||
m_get_bambulab_host = nullptr;
|
||||
m_get_user_selected_machine = nullptr;
|
||||
m_set_user_selected_machine = nullptr;
|
||||
m_start_print = nullptr;
|
||||
m_start_local_print_with_record = nullptr;
|
||||
m_start_send_gcode_to_sdcard = nullptr;
|
||||
m_start_local_print = nullptr;
|
||||
m_start_sdcard_print = nullptr;
|
||||
m_get_user_presets = nullptr;
|
||||
m_request_setting_id = nullptr;
|
||||
m_put_setting = nullptr;
|
||||
m_get_setting_list = nullptr;
|
||||
m_get_setting_list2 = nullptr;
|
||||
m_delete_setting = nullptr;
|
||||
m_get_studio_info_url = nullptr;
|
||||
m_set_extra_http_header = nullptr;
|
||||
m_get_my_message = nullptr;
|
||||
m_check_user_task_report = nullptr;
|
||||
m_get_user_print_info = nullptr;
|
||||
m_get_user_tasks = nullptr;
|
||||
m_get_printer_firmware = nullptr;
|
||||
m_get_task_plate_index = nullptr;
|
||||
m_get_user_info = nullptr;
|
||||
m_request_bind_ticket = nullptr;
|
||||
m_get_subtask_info = nullptr;
|
||||
m_get_slice_info = nullptr;
|
||||
m_query_bind_status = nullptr;
|
||||
m_modify_printer_name = nullptr;
|
||||
m_get_camera_url = nullptr;
|
||||
m_get_design_staffpick = nullptr;
|
||||
m_start_publish = nullptr;
|
||||
m_get_model_publish_url = nullptr;
|
||||
m_get_subtask = nullptr;
|
||||
m_get_model_mall_home_url = nullptr;
|
||||
m_get_model_mall_detail_url = nullptr;
|
||||
m_get_my_profile = nullptr;
|
||||
m_track_enable = nullptr;
|
||||
m_track_remove_files = nullptr;
|
||||
m_track_event = nullptr;
|
||||
m_track_header = nullptr;
|
||||
m_track_update_property = nullptr;
|
||||
m_track_get_property = nullptr;
|
||||
m_put_model_mall_rating = nullptr;
|
||||
m_get_oss_config = nullptr;
|
||||
m_put_rating_picture_oss = nullptr;
|
||||
m_get_model_mall_rating_result = nullptr;
|
||||
m_get_mw_user_preference = nullptr;
|
||||
m_get_mw_user_4ulist = nullptr;
|
||||
}
|
||||
|
||||
std::vector<NetworkLibraryVersionInfo> get_all_available_versions()
|
||||
{
|
||||
std::vector<NetworkLibraryVersionInfo> result;
|
||||
std::set<std::string> known_base_versions;
|
||||
std::set<std::string> all_known_versions;
|
||||
|
||||
for (size_t i = 0; i < AVAILABLE_NETWORK_VERSIONS_COUNT; ++i) {
|
||||
result.push_back(NetworkLibraryVersionInfo::from_static(AVAILABLE_NETWORK_VERSIONS[i]));
|
||||
known_base_versions.insert(AVAILABLE_NETWORK_VERSIONS[i].version);
|
||||
all_known_versions.insert(AVAILABLE_NETWORK_VERSIONS[i].version);
|
||||
}
|
||||
|
||||
std::vector<std::string> discovered = BBLNetworkPlugin::scan_plugin_versions();
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> suffixed_versions;
|
||||
|
||||
for (const auto& version : discovered) {
|
||||
if (all_known_versions.count(version) > 0)
|
||||
continue;
|
||||
|
||||
std::string base = extract_base_version(version);
|
||||
std::string suffix = extract_suffix(version);
|
||||
|
||||
if (suffix.empty())
|
||||
continue;
|
||||
|
||||
if (known_base_versions.count(base) == 0)
|
||||
continue;
|
||||
|
||||
suffixed_versions.emplace_back(base, version);
|
||||
all_known_versions.insert(version);
|
||||
}
|
||||
|
||||
std::sort(suffixed_versions.begin(), suffixed_versions.end(),
|
||||
[](const auto& a, const auto& b) {
|
||||
if (a.first != b.first) return a.first > b.first;
|
||||
return a.second < b.second;
|
||||
});
|
||||
|
||||
for (const auto& [base, full] : suffixed_versions) {
|
||||
size_t insert_pos = 0;
|
||||
for (size_t i = 0; i < result.size(); ++i) {
|
||||
if (result[i].base_version == base) {
|
||||
insert_pos = i + 1;
|
||||
while (insert_pos < result.size() &&
|
||||
result[insert_pos].base_version == base) {
|
||||
++insert_pos;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string sfx = extract_suffix(full);
|
||||
result.insert(result.begin() + insert_pos,
|
||||
NetworkLibraryVersionInfo::from_discovered(full, base, sfx));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
515
src/slic3r/Utils/BBLNetworkPlugin.hpp
Normal file
515
src/slic3r/Utils/BBLNetworkPlugin.hpp
Normal file
@@ -0,0 +1,515 @@
|
||||
#ifndef __BBL_NETWORK_PLUGIN_HPP__
|
||||
#define __BBL_NETWORK_PLUGIN_HPP__
|
||||
|
||||
#include "bambu_networking.hpp"
|
||||
#include "libslic3r/ProjectTask.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// ============================================================================
|
||||
// Function Pointer Types (copied from NetworkAgent.hpp)
|
||||
// ============================================================================
|
||||
|
||||
typedef bool (*func_check_debug_consistent)(bool is_debug);
|
||||
typedef std::string (*func_get_version)(void);
|
||||
typedef void* (*func_create_agent)(std::string log_dir);
|
||||
typedef int (*func_destroy_agent)(void *agent);
|
||||
typedef int (*func_init_log)(void *agent);
|
||||
typedef int (*func_set_config_dir)(void *agent, std::string config_dir);
|
||||
typedef int (*func_set_cert_file)(void *agent, std::string folder, std::string filename);
|
||||
typedef int (*func_set_country_code)(void *agent, std::string country_code);
|
||||
typedef int (*func_start)(void *agent);
|
||||
typedef int (*func_set_on_ssdp_msg_fn)(void *agent, OnMsgArrivedFn fn);
|
||||
typedef int (*func_set_on_user_login_fn)(void *agent, OnUserLoginFn fn);
|
||||
typedef int (*func_set_on_printer_connected_fn)(void *agent, OnPrinterConnectedFn fn);
|
||||
typedef int (*func_set_on_server_connected_fn)(void *agent, OnServerConnectedFn fn);
|
||||
typedef int (*func_set_on_http_error_fn)(void *agent, OnHttpErrorFn fn);
|
||||
typedef int (*func_set_get_country_code_fn)(void *agent, GetCountryCodeFn fn);
|
||||
typedef int (*func_set_on_subscribe_failure_fn)(void *agent, GetSubscribeFailureFn fn);
|
||||
typedef int (*func_set_on_message_fn)(void *agent, OnMessageFn fn);
|
||||
typedef int (*func_set_on_user_message_fn)(void *agent, OnMessageFn fn);
|
||||
typedef int (*func_set_on_local_connect_fn)(void *agent, OnLocalConnectedFn fn);
|
||||
typedef int (*func_set_on_local_message_fn)(void *agent, OnMessageFn fn);
|
||||
typedef int (*func_set_queue_on_main_fn)(void *agent, QueueOnMainFn fn);
|
||||
typedef int (*func_connect_server)(void *agent);
|
||||
typedef bool (*func_is_server_connected)(void *agent);
|
||||
typedef int (*func_refresh_connection)(void *agent);
|
||||
typedef int (*func_start_subscribe)(void *agent, std::string module);
|
||||
typedef int (*func_stop_subscribe)(void *agent, std::string module);
|
||||
typedef int (*func_add_subscribe)(void *agent, std::vector<std::string> dev_list);
|
||||
typedef int (*func_del_subscribe)(void *agent, std::vector<std::string> dev_list);
|
||||
typedef void (*func_enable_multi_machine)(void *agent, bool enable);
|
||||
typedef int (*func_send_message)(void *agent, std::string dev_id, std::string json_str, int qos, int flag);
|
||||
typedef int (*func_connect_printer)(void *agent, std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl);
|
||||
typedef int (*func_disconnect_printer)(void *agent);
|
||||
typedef int (*func_send_message_to_printer)(void *agent, std::string dev_id, std::string json_str, int qos, int flag);
|
||||
typedef int (*func_check_cert)(void* agent);
|
||||
typedef void (*func_install_device_cert)(void* agent, std::string dev_id, bool lan_only);
|
||||
typedef bool (*func_start_discovery)(void *agent, bool start, bool sending);
|
||||
typedef int (*func_change_user)(void *agent, std::string user_info);
|
||||
typedef bool (*func_is_user_login)(void *agent);
|
||||
typedef int (*func_user_logout)(void *agent, bool request);
|
||||
typedef std::string (*func_get_user_id)(void *agent);
|
||||
typedef std::string (*func_get_user_name)(void *agent);
|
||||
typedef std::string (*func_get_user_avatar)(void *agent);
|
||||
typedef std::string (*func_get_user_nickanme)(void *agent);
|
||||
typedef std::string (*func_build_login_cmd)(void *agent);
|
||||
typedef std::string (*func_build_logout_cmd)(void *agent);
|
||||
typedef std::string (*func_build_login_info)(void *agent);
|
||||
typedef int (*func_ping_bind)(void *agent, std::string ping_code);
|
||||
typedef int (*func_bind_detect)(void *agent, std::string dev_ip, std::string sec_link, detectResult& detect);
|
||||
typedef int (*func_set_server_callback)(void *agent, OnServerErrFn fn);
|
||||
typedef int (*func_bind)(void *agent, std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn);
|
||||
typedef int (*func_unbind)(void *agent, std::string dev_id);
|
||||
typedef std::string (*func_get_bambulab_host)(void *agent);
|
||||
typedef std::string (*func_get_user_selected_machine)(void *agent);
|
||||
typedef int (*func_set_user_selected_machine)(void *agent, std::string dev_id);
|
||||
typedef int (*func_start_print)(void *agent, PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
|
||||
typedef int (*func_start_local_print_with_record)(void *agent, PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
|
||||
typedef int (*func_start_send_gcode_to_sdcard)(void *agent, PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
|
||||
typedef int (*func_start_local_print)(void *agent, PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
|
||||
typedef int (*func_start_sdcard_print)(void *agent, PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
|
||||
typedef int (*func_get_user_presets)(void *agent, std::map<std::string, std::map<std::string, std::string>>* user_presets);
|
||||
typedef std::string (*func_request_setting_id)(void *agent, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code);
|
||||
typedef int (*func_put_setting)(void *agent, std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code);
|
||||
typedef int (*func_get_setting_list)(void *agent, std::string bundle_version, ProgressFn pro_fn, WasCancelledFn cancel_fn);
|
||||
typedef int (*func_get_setting_list2)(void *agent, std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn, WasCancelledFn cancel_fn);
|
||||
typedef int (*func_delete_setting)(void *agent, std::string setting_id);
|
||||
typedef std::string (*func_get_studio_info_url)(void *agent);
|
||||
typedef int (*func_set_extra_http_header)(void *agent, std::map<std::string, std::string> extra_headers);
|
||||
typedef int (*func_get_my_message)(void *agent, int type, int after, int limit, unsigned int* http_code, std::string* http_body);
|
||||
typedef int (*func_check_user_task_report)(void *agent, int* task_id, bool* printable);
|
||||
typedef int (*func_get_user_print_info)(void *agent, unsigned int* http_code, std::string* http_body);
|
||||
typedef int (*func_get_user_tasks)(void *agent, TaskQueryParams params, std::string* http_body);
|
||||
typedef int (*func_get_printer_firmware)(void *agent, std::string dev_id, unsigned* http_code, std::string* http_body);
|
||||
typedef int (*func_get_task_plate_index)(void *agent, std::string task_id, int* plate_index);
|
||||
typedef int (*func_get_user_info)(void *agent, int* identifier);
|
||||
typedef int (*func_request_bind_ticket)(void *agent, std::string* ticket);
|
||||
typedef int (*func_get_subtask_info)(void *agent, std::string subtask_id, std::string* task_json, unsigned int* http_code, std::string *http_body);
|
||||
typedef int (*func_get_slice_info)(void *agent, std::string project_id, std::string profile_id, int plate_index, std::string* slice_json);
|
||||
typedef int (*func_query_bind_status)(void *agent, std::vector<std::string> query_list, unsigned int* http_code, std::string* http_body);
|
||||
typedef int (*func_modify_printer_name)(void *agent, std::string dev_id, std::string dev_name);
|
||||
typedef int (*func_get_camera_url)(void *agent, std::string dev_id, std::function<void(std::string)> callback);
|
||||
typedef int (*func_get_design_staffpick)(void *agent, int offset, int limit, std::function<void(std::string)> callback);
|
||||
typedef int (*func_start_pubilsh)(void *agent, PublishParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, std::string* out);
|
||||
typedef int (*func_get_model_publish_url)(void *agent, std::string* url);
|
||||
typedef int (*func_get_subtask)(void *agent, BBLModelTask* task, OnGetSubTaskFn getsub_fn);
|
||||
typedef int (*func_get_model_mall_home_url)(void *agent, std::string* url);
|
||||
typedef int (*func_get_model_mall_detail_url)(void *agent, std::string* url, std::string id);
|
||||
typedef int (*func_get_my_profile)(void *agent, std::string token, unsigned int *http_code, std::string *http_body);
|
||||
typedef int (*func_track_enable)(void *agent, bool enable);
|
||||
typedef int (*func_track_remove_files)(void *agent);
|
||||
typedef int (*func_track_event)(void *agent, std::string evt_key, std::string content);
|
||||
typedef int (*func_track_header)(void *agent, std::string header);
|
||||
typedef int (*func_track_update_property)(void *agent, std::string name, std::string value, std::string type);
|
||||
typedef int (*func_track_get_property)(void *agent, std::string name, std::string& value, std::string type);
|
||||
typedef int (*func_put_model_mall_rating_url)(void *agent, int rating_id, int score, std::string content, std::vector<std::string> images, unsigned int &http_code, std::string &http_error);
|
||||
typedef int (*func_get_oss_config)(void *agent, std::string &config, std::string country_code, unsigned int &http_code, std::string &http_error);
|
||||
typedef int (*func_put_rating_picture_oss)(void *agent, std::string &config, std::string &pic_oss_path, std::string model_id, int profile_id, unsigned int &http_code, std::string &http_error);
|
||||
typedef int (*func_get_model_mall_rating_result)(void *agent, int job_id, std::string &rating_result, unsigned int &http_code, std::string &http_error);
|
||||
typedef int (*func_get_mw_user_preference)(void *agent, std::function<void(std::string)> callback);
|
||||
typedef int (*func_get_mw_user_4ulist)(void *agent, int seed, int limit, std::function<void(std::string)> callback);
|
||||
|
||||
// Legacy function pointer types (for older DLL versions)
|
||||
typedef int (*func_start_print_legacy)(void *agent, PrintParams_Legacy params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
|
||||
typedef int (*func_start_local_print_with_record_legacy)(void *agent, PrintParams_Legacy params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
|
||||
typedef int (*func_start_send_gcode_to_sdcard_legacy)(void *agent, PrintParams_Legacy params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
|
||||
typedef int (*func_start_local_print_legacy)(void *agent, PrintParams_Legacy params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
|
||||
typedef int (*func_start_sdcard_print_legacy)(void* agent, PrintParams_Legacy params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
|
||||
typedef int (*func_send_message_legacy)(void* agent, std::string dev_id, std::string json_str, int qos);
|
||||
typedef int (*func_send_message_to_printer_legacy)(void* agent, std::string dev_id, std::string json_str, int qos);
|
||||
|
||||
/**
|
||||
* BBLNetworkPlugin - Singleton managing the Bambu Lab network DLL.
|
||||
*
|
||||
* Responsibilities:
|
||||
* - Owns the DLL module handle (netwoking_module)
|
||||
* - Owns the DLL source module handle (source_module)
|
||||
* - Manages the shared void* agent handle
|
||||
* - Provides all function pointers to BBL agents
|
||||
*
|
||||
* Usage:
|
||||
* auto& plugin = BBLNetworkPlugin::instance();
|
||||
* if (plugin.initialize(version)) {
|
||||
* plugin.create_agent(log_dir);
|
||||
* // Now BBLCloudServiceAgent/BBLPrinterAgent can use plugin
|
||||
* }
|
||||
*/
|
||||
class BBLNetworkPlugin {
|
||||
public:
|
||||
// Singleton access
|
||||
static BBLNetworkPlugin& instance();
|
||||
|
||||
// Delete copy/move
|
||||
BBLNetworkPlugin(const BBLNetworkPlugin&) = delete;
|
||||
BBLNetworkPlugin& operator=(const BBLNetworkPlugin&) = delete;
|
||||
BBLNetworkPlugin(BBLNetworkPlugin&&) = delete;
|
||||
BBLNetworkPlugin& operator=(BBLNetworkPlugin&&) = delete;
|
||||
|
||||
// ========================================================================
|
||||
// Module Lifecycle
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Load the network DLL from the plugins folder.
|
||||
* @param using_backup If true, look in plugins/backup folder
|
||||
* @param version Required version string (e.g., "01.09.05.01")
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int initialize(bool using_backup = false, const std::string& version = "");
|
||||
|
||||
/**
|
||||
* Unload the network DLL and clear all function pointers.
|
||||
* @return 0 on success
|
||||
*/
|
||||
int unload();
|
||||
|
||||
/**
|
||||
* Destroy the singleton instance.
|
||||
* Safe to call multiple times - does nothing if already destroyed.
|
||||
* Must be called during application shutdown before main() returns.
|
||||
*/
|
||||
static void shutdown();
|
||||
|
||||
/**
|
||||
* Check if DLL is currently loaded.
|
||||
*/
|
||||
bool is_loaded() const;
|
||||
|
||||
/**
|
||||
* Get the plugin version string.
|
||||
*/
|
||||
std::string get_version() const;
|
||||
|
||||
// ========================================================================
|
||||
// Agent Lifecycle
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Create the shared agent handle.
|
||||
* Only one agent can exist at a time.
|
||||
* @param log_dir Directory for log files
|
||||
* @return The created agent handle, or nullptr on failure
|
||||
*/
|
||||
void* create_agent(const std::string& log_dir);
|
||||
|
||||
/**
|
||||
* Destroy the shared agent handle.
|
||||
* @return 0 on success
|
||||
*/
|
||||
int destroy_agent();
|
||||
|
||||
/**
|
||||
* Get the current agent handle.
|
||||
* Returns nullptr if no agent created.
|
||||
*/
|
||||
void* get_agent() const { return m_agent; }
|
||||
|
||||
/**
|
||||
* Check if an agent has been created.
|
||||
*/
|
||||
bool has_agent() const { return m_agent != nullptr; }
|
||||
|
||||
// ========================================================================
|
||||
// DLL Module Accessors
|
||||
// ========================================================================
|
||||
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
HMODULE get_networking_module() const { return m_networking_module; }
|
||||
HMODULE get_source_module();
|
||||
#else
|
||||
void* get_networking_module() const { return m_networking_module; }
|
||||
void* get_source_module();
|
||||
#endif
|
||||
|
||||
void* get_function(const char* name);
|
||||
|
||||
// Aliases for backward compatibility with NetworkAgent API
|
||||
void* get_network_function(const char* name) { return get_function(name); }
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
HMODULE get_bambu_source_entry() { return get_source_module(); }
|
||||
#else
|
||||
void* get_bambu_source_entry() { return get_source_module(); }
|
||||
#endif
|
||||
|
||||
// ========================================================================
|
||||
// Utility Methods
|
||||
// ========================================================================
|
||||
|
||||
static std::string get_libpath_in_current_directory(const std::string& library_name);
|
||||
static std::string get_versioned_library_path(const std::string& version);
|
||||
static bool versioned_library_exists(const std::string& version);
|
||||
static bool legacy_library_exists();
|
||||
static void remove_legacy_library();
|
||||
static std::vector<std::string> scan_plugin_versions();
|
||||
|
||||
// ========================================================================
|
||||
// Error Handling
|
||||
// ========================================================================
|
||||
|
||||
NetworkLibraryLoadError get_load_error() const { return m_load_error; }
|
||||
void clear_load_error();
|
||||
void set_load_error(const std::string& message,
|
||||
const std::string& technical_details,
|
||||
const std::string& attempted_path);
|
||||
|
||||
// ========================================================================
|
||||
// Legacy Network Flag
|
||||
// ========================================================================
|
||||
|
||||
bool use_legacy_network() const { return m_use_legacy_network; }
|
||||
void set_use_legacy_network(bool legacy) { m_use_legacy_network = legacy; }
|
||||
|
||||
// ========================================================================
|
||||
// Function Pointer Accessors
|
||||
// ========================================================================
|
||||
|
||||
func_check_debug_consistent get_check_debug_consistent() const { return m_check_debug_consistent; }
|
||||
func_get_version get_get_version() const { return m_get_version; }
|
||||
func_create_agent get_create_agent() const { return m_create_agent; }
|
||||
func_destroy_agent get_destroy_agent() const { return m_destroy_agent; }
|
||||
func_init_log get_init_log() const { return m_init_log; }
|
||||
func_set_config_dir get_set_config_dir() const { return m_set_config_dir; }
|
||||
func_set_cert_file get_set_cert_file() const { return m_set_cert_file; }
|
||||
func_set_country_code get_set_country_code() const { return m_set_country_code; }
|
||||
func_start get_start() const { return m_start; }
|
||||
func_set_on_ssdp_msg_fn get_set_on_ssdp_msg_fn() const { return m_set_on_ssdp_msg_fn; }
|
||||
func_set_on_user_login_fn get_set_on_user_login_fn() const { return m_set_on_user_login_fn; }
|
||||
func_set_on_printer_connected_fn get_set_on_printer_connected_fn() const { return m_set_on_printer_connected_fn; }
|
||||
func_set_on_server_connected_fn get_set_on_server_connected_fn() const { return m_set_on_server_connected_fn; }
|
||||
func_set_on_http_error_fn get_set_on_http_error_fn() const { return m_set_on_http_error_fn; }
|
||||
func_set_get_country_code_fn get_set_get_country_code_fn() const { return m_set_get_country_code_fn; }
|
||||
func_set_on_subscribe_failure_fn get_set_on_subscribe_failure_fn() const { return m_set_on_subscribe_failure_fn; }
|
||||
func_set_on_message_fn get_set_on_message_fn() const { return m_set_on_message_fn; }
|
||||
func_set_on_user_message_fn get_set_on_user_message_fn() const { return m_set_on_user_message_fn; }
|
||||
func_set_on_local_connect_fn get_set_on_local_connect_fn() const { return m_set_on_local_connect_fn; }
|
||||
func_set_on_local_message_fn get_set_on_local_message_fn() const { return m_set_on_local_message_fn; }
|
||||
func_set_queue_on_main_fn get_set_queue_on_main_fn() const { return m_set_queue_on_main_fn; }
|
||||
func_connect_server get_connect_server() const { return m_connect_server; }
|
||||
func_is_server_connected get_is_server_connected() const { return m_is_server_connected; }
|
||||
func_refresh_connection get_refresh_connection() const { return m_refresh_connection; }
|
||||
func_start_subscribe get_start_subscribe() const { return m_start_subscribe; }
|
||||
func_stop_subscribe get_stop_subscribe() const { return m_stop_subscribe; }
|
||||
func_add_subscribe get_add_subscribe() const { return m_add_subscribe; }
|
||||
func_del_subscribe get_del_subscribe() const { return m_del_subscribe; }
|
||||
func_enable_multi_machine get_enable_multi_machine() const { return m_enable_multi_machine; }
|
||||
func_send_message get_send_message() const { return m_send_message; }
|
||||
func_connect_printer get_connect_printer() const { return m_connect_printer; }
|
||||
func_disconnect_printer get_disconnect_printer() const { return m_disconnect_printer; }
|
||||
func_send_message_to_printer get_send_message_to_printer() const { return m_send_message_to_printer; }
|
||||
func_check_cert get_check_cert() const { return m_check_cert; }
|
||||
func_install_device_cert get_install_device_cert() const { return m_install_device_cert; }
|
||||
func_start_discovery get_start_discovery() const { return m_start_discovery; }
|
||||
func_change_user get_change_user() const { return m_change_user; }
|
||||
func_is_user_login get_is_user_login() const { return m_is_user_login; }
|
||||
func_user_logout get_user_logout() const { return m_user_logout; }
|
||||
func_get_user_id get_get_user_id() const { return m_get_user_id; }
|
||||
func_get_user_name get_get_user_name() const { return m_get_user_name; }
|
||||
func_get_user_avatar get_get_user_avatar() const { return m_get_user_avatar; }
|
||||
func_get_user_nickanme get_get_user_nickanme() const { return m_get_user_nickanme; }
|
||||
func_build_login_cmd get_build_login_cmd() const { return m_build_login_cmd; }
|
||||
func_build_logout_cmd get_build_logout_cmd() const { return m_build_logout_cmd; }
|
||||
func_build_login_info get_build_login_info() const { return m_build_login_info; }
|
||||
func_ping_bind get_ping_bind() const { return m_ping_bind; }
|
||||
func_bind_detect get_bind_detect() const { return m_bind_detect; }
|
||||
func_set_server_callback get_set_server_callback() const { return m_set_server_callback; }
|
||||
func_bind get_bind() const { return m_bind; }
|
||||
func_unbind get_unbind() const { return m_unbind; }
|
||||
func_get_bambulab_host get_get_bambulab_host() const { return m_get_bambulab_host; }
|
||||
func_get_user_selected_machine get_get_user_selected_machine() const { return m_get_user_selected_machine; }
|
||||
func_set_user_selected_machine get_set_user_selected_machine() const { return m_set_user_selected_machine; }
|
||||
func_start_print get_start_print() const { return m_start_print; }
|
||||
func_start_local_print_with_record get_start_local_print_with_record() const { return m_start_local_print_with_record; }
|
||||
func_start_send_gcode_to_sdcard get_start_send_gcode_to_sdcard() const { return m_start_send_gcode_to_sdcard; }
|
||||
func_start_local_print get_start_local_print() const { return m_start_local_print; }
|
||||
func_start_sdcard_print get_start_sdcard_print() const { return m_start_sdcard_print; }
|
||||
func_get_user_presets get_get_user_presets() const { return m_get_user_presets; }
|
||||
func_request_setting_id get_request_setting_id() const { return m_request_setting_id; }
|
||||
func_put_setting get_put_setting() const { return m_put_setting; }
|
||||
func_get_setting_list get_get_setting_list() const { return m_get_setting_list; }
|
||||
func_get_setting_list2 get_get_setting_list2() const { return m_get_setting_list2; }
|
||||
func_delete_setting get_delete_setting() const { return m_delete_setting; }
|
||||
func_get_studio_info_url get_get_studio_info_url() const { return m_get_studio_info_url; }
|
||||
func_set_extra_http_header get_set_extra_http_header() const { return m_set_extra_http_header; }
|
||||
func_get_my_message get_get_my_message() const { return m_get_my_message; }
|
||||
func_check_user_task_report get_check_user_task_report() const { return m_check_user_task_report; }
|
||||
func_get_user_print_info get_get_user_print_info() const { return m_get_user_print_info; }
|
||||
func_get_user_tasks get_get_user_tasks() const { return m_get_user_tasks; }
|
||||
func_get_printer_firmware get_get_printer_firmware() const { return m_get_printer_firmware; }
|
||||
func_get_task_plate_index get_get_task_plate_index() const { return m_get_task_plate_index; }
|
||||
func_get_user_info get_get_user_info() const { return m_get_user_info; }
|
||||
func_request_bind_ticket get_request_bind_ticket() const { return m_request_bind_ticket; }
|
||||
func_get_subtask_info get_get_subtask_info() const { return m_get_subtask_info; }
|
||||
func_get_slice_info get_get_slice_info() const { return m_get_slice_info; }
|
||||
func_query_bind_status get_query_bind_status() const { return m_query_bind_status; }
|
||||
func_modify_printer_name get_modify_printer_name() const { return m_modify_printer_name; }
|
||||
func_get_camera_url get_get_camera_url() const { return m_get_camera_url; }
|
||||
func_get_design_staffpick get_get_design_staffpick() const { return m_get_design_staffpick; }
|
||||
func_start_pubilsh get_start_publish() const { return m_start_publish; }
|
||||
func_get_model_publish_url get_get_model_publish_url() const { return m_get_model_publish_url; }
|
||||
func_get_subtask get_get_subtask() const { return m_get_subtask; }
|
||||
func_get_model_mall_home_url get_get_model_mall_home_url() const { return m_get_model_mall_home_url; }
|
||||
func_get_model_mall_detail_url get_get_model_mall_detail_url() const { return m_get_model_mall_detail_url; }
|
||||
func_get_my_profile get_get_my_profile() const { return m_get_my_profile; }
|
||||
func_track_enable get_track_enable() const { return m_track_enable; }
|
||||
func_track_remove_files get_track_remove_files() const { return m_track_remove_files; }
|
||||
func_track_event get_track_event() const { return m_track_event; }
|
||||
func_track_header get_track_header() const { return m_track_header; }
|
||||
func_track_update_property get_track_update_property() const { return m_track_update_property; }
|
||||
func_track_get_property get_track_get_property() const { return m_track_get_property; }
|
||||
func_put_model_mall_rating_url get_put_model_mall_rating() const { return m_put_model_mall_rating; }
|
||||
func_get_oss_config get_get_oss_config() const { return m_get_oss_config; }
|
||||
func_put_rating_picture_oss get_put_rating_picture_oss() const { return m_put_rating_picture_oss; }
|
||||
func_get_model_mall_rating_result get_get_model_mall_rating_result() const { return m_get_model_mall_rating_result; }
|
||||
func_get_mw_user_preference get_get_mw_user_preference() const { return m_get_mw_user_preference; }
|
||||
func_get_mw_user_4ulist get_get_mw_user_4ulist() const { return m_get_mw_user_4ulist; }
|
||||
|
||||
// ========================================================================
|
||||
// Legacy Helper
|
||||
// ========================================================================
|
||||
|
||||
static PrintParams_Legacy as_legacy(PrintParams& param);
|
||||
|
||||
private:
|
||||
// Singleton instance pointer (heap-allocated for explicit lifetime control)
|
||||
static BBLNetworkPlugin* s_instance;
|
||||
|
||||
BBLNetworkPlugin();
|
||||
~BBLNetworkPlugin();
|
||||
|
||||
void load_all_function_pointers();
|
||||
void clear_all_function_pointers();
|
||||
|
||||
// Module handles
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
HMODULE m_networking_module{nullptr};
|
||||
HMODULE m_source_module{nullptr};
|
||||
#else
|
||||
void* m_networking_module{nullptr};
|
||||
void* m_source_module{nullptr};
|
||||
#endif
|
||||
|
||||
// Shared agent handle
|
||||
void* m_agent{nullptr};
|
||||
|
||||
// Load error state
|
||||
NetworkLibraryLoadError m_load_error;
|
||||
|
||||
// Legacy network compatibility flag
|
||||
bool m_use_legacy_network{true};
|
||||
|
||||
// Function pointers
|
||||
func_check_debug_consistent m_check_debug_consistent{nullptr};
|
||||
func_get_version m_get_version{nullptr};
|
||||
func_create_agent m_create_agent{nullptr};
|
||||
func_destroy_agent m_destroy_agent{nullptr};
|
||||
func_init_log m_init_log{nullptr};
|
||||
func_set_config_dir m_set_config_dir{nullptr};
|
||||
func_set_cert_file m_set_cert_file{nullptr};
|
||||
func_set_country_code m_set_country_code{nullptr};
|
||||
func_start m_start{nullptr};
|
||||
func_set_on_ssdp_msg_fn m_set_on_ssdp_msg_fn{nullptr};
|
||||
func_set_on_user_login_fn m_set_on_user_login_fn{nullptr};
|
||||
func_set_on_printer_connected_fn m_set_on_printer_connected_fn{nullptr};
|
||||
func_set_on_server_connected_fn m_set_on_server_connected_fn{nullptr};
|
||||
func_set_on_http_error_fn m_set_on_http_error_fn{nullptr};
|
||||
func_set_get_country_code_fn m_set_get_country_code_fn{nullptr};
|
||||
func_set_on_subscribe_failure_fn m_set_on_subscribe_failure_fn{nullptr};
|
||||
func_set_on_message_fn m_set_on_message_fn{nullptr};
|
||||
func_set_on_user_message_fn m_set_on_user_message_fn{nullptr};
|
||||
func_set_on_local_connect_fn m_set_on_local_connect_fn{nullptr};
|
||||
func_set_on_local_message_fn m_set_on_local_message_fn{nullptr};
|
||||
func_set_queue_on_main_fn m_set_queue_on_main_fn{nullptr};
|
||||
func_connect_server m_connect_server{nullptr};
|
||||
func_is_server_connected m_is_server_connected{nullptr};
|
||||
func_refresh_connection m_refresh_connection{nullptr};
|
||||
func_start_subscribe m_start_subscribe{nullptr};
|
||||
func_stop_subscribe m_stop_subscribe{nullptr};
|
||||
func_add_subscribe m_add_subscribe{nullptr};
|
||||
func_del_subscribe m_del_subscribe{nullptr};
|
||||
func_enable_multi_machine m_enable_multi_machine{nullptr};
|
||||
func_send_message m_send_message{nullptr};
|
||||
func_connect_printer m_connect_printer{nullptr};
|
||||
func_disconnect_printer m_disconnect_printer{nullptr};
|
||||
func_send_message_to_printer m_send_message_to_printer{nullptr};
|
||||
func_check_cert m_check_cert{nullptr};
|
||||
func_install_device_cert m_install_device_cert{nullptr};
|
||||
func_start_discovery m_start_discovery{nullptr};
|
||||
func_change_user m_change_user{nullptr};
|
||||
func_is_user_login m_is_user_login{nullptr};
|
||||
func_user_logout m_user_logout{nullptr};
|
||||
func_get_user_id m_get_user_id{nullptr};
|
||||
func_get_user_name m_get_user_name{nullptr};
|
||||
func_get_user_avatar m_get_user_avatar{nullptr};
|
||||
func_get_user_nickanme m_get_user_nickanme{nullptr};
|
||||
func_build_login_cmd m_build_login_cmd{nullptr};
|
||||
func_build_logout_cmd m_build_logout_cmd{nullptr};
|
||||
func_build_login_info m_build_login_info{nullptr};
|
||||
func_ping_bind m_ping_bind{nullptr};
|
||||
func_bind_detect m_bind_detect{nullptr};
|
||||
func_set_server_callback m_set_server_callback{nullptr};
|
||||
func_bind m_bind{nullptr};
|
||||
func_unbind m_unbind{nullptr};
|
||||
func_get_bambulab_host m_get_bambulab_host{nullptr};
|
||||
func_get_user_selected_machine m_get_user_selected_machine{nullptr};
|
||||
func_set_user_selected_machine m_set_user_selected_machine{nullptr};
|
||||
func_start_print m_start_print{nullptr};
|
||||
func_start_local_print_with_record m_start_local_print_with_record{nullptr};
|
||||
func_start_send_gcode_to_sdcard m_start_send_gcode_to_sdcard{nullptr};
|
||||
func_start_local_print m_start_local_print{nullptr};
|
||||
func_start_sdcard_print m_start_sdcard_print{nullptr};
|
||||
func_get_user_presets m_get_user_presets{nullptr};
|
||||
func_request_setting_id m_request_setting_id{nullptr};
|
||||
func_put_setting m_put_setting{nullptr};
|
||||
func_get_setting_list m_get_setting_list{nullptr};
|
||||
func_get_setting_list2 m_get_setting_list2{nullptr};
|
||||
func_delete_setting m_delete_setting{nullptr};
|
||||
func_get_studio_info_url m_get_studio_info_url{nullptr};
|
||||
func_set_extra_http_header m_set_extra_http_header{nullptr};
|
||||
func_get_my_message m_get_my_message{nullptr};
|
||||
func_check_user_task_report m_check_user_task_report{nullptr};
|
||||
func_get_user_print_info m_get_user_print_info{nullptr};
|
||||
func_get_user_tasks m_get_user_tasks{nullptr};
|
||||
func_get_printer_firmware m_get_printer_firmware{nullptr};
|
||||
func_get_task_plate_index m_get_task_plate_index{nullptr};
|
||||
func_get_user_info m_get_user_info{nullptr};
|
||||
func_request_bind_ticket m_request_bind_ticket{nullptr};
|
||||
func_get_subtask_info m_get_subtask_info{nullptr};
|
||||
func_get_slice_info m_get_slice_info{nullptr};
|
||||
func_query_bind_status m_query_bind_status{nullptr};
|
||||
func_modify_printer_name m_modify_printer_name{nullptr};
|
||||
func_get_camera_url m_get_camera_url{nullptr};
|
||||
func_get_design_staffpick m_get_design_staffpick{nullptr};
|
||||
func_start_pubilsh m_start_publish{nullptr};
|
||||
func_get_model_publish_url m_get_model_publish_url{nullptr};
|
||||
func_get_subtask m_get_subtask{nullptr};
|
||||
func_get_model_mall_home_url m_get_model_mall_home_url{nullptr};
|
||||
func_get_model_mall_detail_url m_get_model_mall_detail_url{nullptr};
|
||||
func_get_my_profile m_get_my_profile{nullptr};
|
||||
func_track_enable m_track_enable{nullptr};
|
||||
func_track_remove_files m_track_remove_files{nullptr};
|
||||
func_track_event m_track_event{nullptr};
|
||||
func_track_header m_track_header{nullptr};
|
||||
func_track_update_property m_track_update_property{nullptr};
|
||||
func_track_get_property m_track_get_property{nullptr};
|
||||
func_put_model_mall_rating_url m_put_model_mall_rating{nullptr};
|
||||
func_get_oss_config m_get_oss_config{nullptr};
|
||||
func_put_rating_picture_oss m_put_rating_picture_oss{nullptr};
|
||||
func_get_model_mall_rating_result m_get_model_mall_rating_result{nullptr};
|
||||
func_get_mw_user_preference m_get_mw_user_preference{nullptr};
|
||||
func_get_mw_user_4ulist m_get_mw_user_4ulist{nullptr};
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // __BBL_NETWORK_PLUGIN_HPP__
|
||||
379
src/slic3r/Utils/BBLPrinterAgent.cpp
Normal file
379
src/slic3r/Utils/BBLPrinterAgent.cpp
Normal file
@@ -0,0 +1,379 @@
|
||||
#include "BBLPrinterAgent.hpp"
|
||||
#include "BBLNetworkPlugin.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
BBLPrinterAgent::BBLPrinterAgent()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "BBLPrinterAgent: Constructor - using BBLNetworkPlugin singleton";
|
||||
}
|
||||
|
||||
BBLPrinterAgent::~BBLPrinterAgent() = default;
|
||||
|
||||
void BBLPrinterAgent::set_cloud_agent(std::shared_ptr<ICloudServiceAgent> cloud)
|
||||
{
|
||||
m_cloud_agent = cloud;
|
||||
// BBL DLL manages tokens internally, so this is just for interface compliance
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Communication
|
||||
// ============================================================================
|
||||
|
||||
int BBLPrinterAgent::send_message(std::string dev_id, std::string json_str, int qos, int flag)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_send_message();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_id, json_str, qos, flag);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_connect_printer();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_id, dev_ip, username, password, use_ssl);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::disconnect_printer()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_disconnect_printer();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_send_message_to_printer();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_id, json_str, qos, flag);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Certificates
|
||||
// ============================================================================
|
||||
|
||||
int BBLPrinterAgent::check_cert()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_check_cert();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void BBLPrinterAgent::install_device_cert(std::string dev_id, bool lan_only)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_install_device_cert();
|
||||
if (func && agent) {
|
||||
func(agent, dev_id, lan_only);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Discovery
|
||||
// ============================================================================
|
||||
|
||||
bool BBLPrinterAgent::start_discovery(bool start, bool sending)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_start_discovery();
|
||||
if (func && agent) {
|
||||
return func(agent, start, sending);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Binding
|
||||
// ============================================================================
|
||||
|
||||
int BBLPrinterAgent::ping_bind(std::string ping_code)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_ping_bind();
|
||||
if (func && agent) {
|
||||
return func(agent, ping_code);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::bind_detect(std::string dev_ip, std::string sec_link, detectResult& detect)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_bind_detect();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_ip, sec_link, detect);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::bind(std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_bind();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_ip, dev_id, sec_link, timezone, improved, update_fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::unbind(std::string dev_id)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_unbind();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_id);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::request_bind_ticket(std::string* ticket)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_request_bind_ticket();
|
||||
if (func && agent) {
|
||||
return func(agent, ticket);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::set_server_callback(OnServerErrFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_server_callback();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Machine Selection
|
||||
// ============================================================================
|
||||
|
||||
std::string BBLPrinterAgent::get_user_selected_machine()
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_get_user_selected_machine();
|
||||
if (func && agent) {
|
||||
return func(agent);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::set_user_selected_machine(std::string dev_id)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_user_selected_machine();
|
||||
if (func && agent) {
|
||||
return func(agent, dev_id);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Agent Information
|
||||
// ============================================================================
|
||||
AgentInfo BBLPrinterAgent::get_agent_info_static()
|
||||
{
|
||||
return AgentInfo{
|
||||
.id = "bbl",
|
||||
.name = "Bambu Lab Printer Agent",
|
||||
.version = "",
|
||||
.description = "Bambu Lab printer agent"
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Print Job Operations
|
||||
// ============================================================================
|
||||
|
||||
int BBLPrinterAgent::start_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_start_print();
|
||||
if (func && agent) {
|
||||
return func(agent, params, update_fn, cancel_fn, wait_fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::start_local_print_with_record(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_start_local_print_with_record();
|
||||
if (func && agent) {
|
||||
return func(agent, params, update_fn, cancel_fn, wait_fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::start_send_gcode_to_sdcard(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_start_send_gcode_to_sdcard();
|
||||
if (func && agent) {
|
||||
return func(agent, params, update_fn, cancel_fn, wait_fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::start_local_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_start_local_print();
|
||||
if (func && agent) {
|
||||
return func(agent, params, update_fn, cancel_fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::start_sdcard_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_start_sdcard_print();
|
||||
if (func && agent) {
|
||||
return func(agent, params, update_fn, cancel_fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Callbacks
|
||||
// ============================================================================
|
||||
|
||||
int BBLPrinterAgent::set_on_ssdp_msg_fn(OnMsgArrivedFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_ssdp_msg_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::set_on_printer_connected_fn(OnPrinterConnectedFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_printer_connected_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::set_on_subscribe_failure_fn(GetSubscribeFailureFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_subscribe_failure_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::set_on_message_fn(OnMessageFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_message_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::set_on_user_message_fn(OnMessageFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_user_message_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::set_on_local_connect_fn(OnLocalConnectedFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_local_connect_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::set_on_local_message_fn(OnMessageFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_on_local_message_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::set_queue_on_main_fn(QueueOnMainFn fn)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
auto agent = plugin.get_agent();
|
||||
auto func = plugin.get_set_queue_on_main_fn();
|
||||
if (func && agent) {
|
||||
return func(agent, fn);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Filament Operations
|
||||
// ============================================================================
|
||||
|
||||
FilamentSyncMode BBLPrinterAgent::get_filament_sync_mode() const
|
||||
{
|
||||
// BBL uses MQTT subscription for real-time filament updates
|
||||
return FilamentSyncMode::subscription;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
86
src/slic3r/Utils/BBLPrinterAgent.hpp
Normal file
86
src/slic3r/Utils/BBLPrinterAgent.hpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#ifndef __BBL_PRINTER_AGENT_HPP__
|
||||
#define __BBL_PRINTER_AGENT_HPP__
|
||||
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "ICloudServiceAgent.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
/**
|
||||
* BBLPrinterAgent - BBL DLL wrapper implementation of IPrinterAgent.
|
||||
*
|
||||
* Delegates all printer operations to the proprietary BBL network DLL
|
||||
* through function pointers obtained from BBLNetworkPlugin singleton.
|
||||
*/
|
||||
class BBLPrinterAgent : public IPrinterAgent {
|
||||
public:
|
||||
BBLPrinterAgent();
|
||||
~BBLPrinterAgent() override;
|
||||
|
||||
// Cloud Agent Dependency (not used by BBL - tokens managed internally)
|
||||
void set_cloud_agent(std::shared_ptr<ICloudServiceAgent> cloud) override;
|
||||
|
||||
// ========================================================================
|
||||
// IPrinterAgent Interface Implementation
|
||||
// ========================================================================
|
||||
|
||||
// Communication
|
||||
int send_message(std::string dev_id, std::string json_str, int qos, int flag) override;
|
||||
int connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl) override;
|
||||
int disconnect_printer() override;
|
||||
int send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag) override;
|
||||
|
||||
// Certificates
|
||||
int check_cert() override;
|
||||
void install_device_cert(std::string dev_id, bool lan_only) override;
|
||||
|
||||
// Discovery
|
||||
bool start_discovery(bool start, bool sending) override;
|
||||
|
||||
// Binding
|
||||
int ping_bind(std::string ping_code) override;
|
||||
int bind_detect(std::string dev_ip, std::string sec_link, detectResult& detect) override;
|
||||
int bind(std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn) override;
|
||||
int unbind(std::string dev_id) override;
|
||||
int request_bind_ticket(std::string* ticket) override;
|
||||
int set_server_callback(OnServerErrFn fn) override;
|
||||
|
||||
// Machine Selection
|
||||
std::string get_user_selected_machine() override;
|
||||
int set_user_selected_machine(std::string dev_id) override;
|
||||
|
||||
/**
|
||||
* Get agent information.
|
||||
*
|
||||
* @return AgentInfo struct containing agent identification and descriptive information
|
||||
*/
|
||||
static AgentInfo get_agent_info_static();
|
||||
AgentInfo get_agent_info() override { return get_agent_info_static(); }
|
||||
|
||||
// Print Job Operations
|
||||
int start_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) override;
|
||||
int start_local_print_with_record(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) override;
|
||||
int start_send_gcode_to_sdcard(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) override;
|
||||
int start_local_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn) override;
|
||||
int start_sdcard_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn) override;
|
||||
|
||||
// Callbacks
|
||||
int set_on_ssdp_msg_fn(OnMsgArrivedFn fn) override;
|
||||
int set_on_printer_connected_fn(OnPrinterConnectedFn fn) override;
|
||||
int set_on_subscribe_failure_fn(GetSubscribeFailureFn fn) override;
|
||||
int set_on_message_fn(OnMessageFn fn) override;
|
||||
int set_on_user_message_fn(OnMessageFn fn) override;
|
||||
int set_on_local_connect_fn(OnLocalConnectedFn fn) override;
|
||||
int set_on_local_message_fn(OnMessageFn fn) override;
|
||||
int set_queue_on_main_fn(QueueOnMainFn fn) override;
|
||||
FilamentSyncMode get_filament_sync_mode() const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ICloudServiceAgent> m_cloud_agent;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // __BBL_PRINTER_AGENT_HPP__
|
||||
@@ -110,6 +110,9 @@ struct Http::priv
|
||||
::curl_httppost *form_end;
|
||||
::curl_mime* mime;
|
||||
::curl_slist *headerlist;
|
||||
// For debug printing
|
||||
std::string url;
|
||||
std::string method;
|
||||
// Used for reading the body
|
||||
std::string buffer;
|
||||
// Used for storing file streams added as multipart form parts
|
||||
@@ -170,6 +173,8 @@ Http::priv::priv(const std::string &url)
|
||||
, form_end(nullptr)
|
||||
, mime(nullptr)
|
||||
, headerlist(nullptr)
|
||||
, url(url)
|
||||
, method("GET")
|
||||
, error_buffer(CURL_ERROR_SIZE + 1, '\0')
|
||||
, limit(0)
|
||||
, cancel(false)
|
||||
@@ -757,6 +762,74 @@ void Http::cancel()
|
||||
if (p) { p->cancel = true; }
|
||||
}
|
||||
|
||||
void Http::print() const
|
||||
{
|
||||
if (!p) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Http::print() - no request data";
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostringstream cmd;
|
||||
cmd << "curl";
|
||||
|
||||
// Method
|
||||
if (p->method != "GET") {
|
||||
cmd << " -X " << p->method;
|
||||
}
|
||||
|
||||
// URL
|
||||
cmd << " '" << p->url << "'";
|
||||
|
||||
// Headers (iterate through curl_slist)
|
||||
::curl_slist *header = p->headerlist;
|
||||
while (header) {
|
||||
// Skip empty "Expect:" header we add by default
|
||||
if (header->data && std::string(header->data) != "Expect:") {
|
||||
cmd << " \\\n -H '" << header->data << "'";
|
||||
}
|
||||
header = header->next;
|
||||
}
|
||||
|
||||
// Form fields (multipart) - iterate through curl_httppost
|
||||
::curl_httppost *formpost = p->form;
|
||||
while (formpost) {
|
||||
if (formpost->showfilename) {
|
||||
// File upload (showfilename is set when CURLFORM_FILENAME is used)
|
||||
cmd << " \\\n -F '" << formpost->name << "=@" << formpost->showfilename << "'";
|
||||
} else if (formpost->contents) {
|
||||
// Regular form field with contents
|
||||
cmd << " \\\n -F '" << formpost->name << "=" << formpost->contents << "'";
|
||||
} else {
|
||||
// Stream or other type without direct contents
|
||||
cmd << " \\\n -F '" << formpost->name << "=<data>'";
|
||||
}
|
||||
formpost = formpost->next;
|
||||
}
|
||||
|
||||
// Post body
|
||||
if (!p->postfields.empty()) {
|
||||
// Escape single quotes in the body for shell safety
|
||||
std::string escaped_body = p->postfields;
|
||||
size_t pos = 0;
|
||||
while ((pos = escaped_body.find('\'', pos)) != std::string::npos) {
|
||||
escaped_body.replace(pos, 1, "'\\''");
|
||||
pos += 4;
|
||||
}
|
||||
// Truncate if too long for display
|
||||
if (escaped_body.length() > 1000) {
|
||||
escaped_body = escaped_body.substr(0, 1000) + "...<truncated>";
|
||||
}
|
||||
cmd << " \\\n -d '" << escaped_body << "'";
|
||||
}
|
||||
|
||||
// Put file
|
||||
if (p->putFile) {
|
||||
cmd << " \\\n --upload-file <file-stream>";
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Http request:\n" << cmd.str();
|
||||
}
|
||||
|
||||
Http Http::get(std::string url)
|
||||
{
|
||||
return Http{std::move(url)};
|
||||
@@ -765,6 +838,7 @@ Http Http::get(std::string url)
|
||||
Http Http::post(std::string url)
|
||||
{
|
||||
Http http{std::move(url)};
|
||||
http.p->method = "POST";
|
||||
curl_easy_setopt(http.p->curl, CURLOPT_POST, 1L);
|
||||
return http;
|
||||
}
|
||||
@@ -772,6 +846,7 @@ Http Http::post(std::string url)
|
||||
Http Http::put(std::string url)
|
||||
{
|
||||
Http http{std::move(url)};
|
||||
http.p->method = "PUT";
|
||||
curl_easy_setopt(http.p->curl, CURLOPT_UPLOAD, 1L);
|
||||
return http;
|
||||
}
|
||||
@@ -779,6 +854,7 @@ Http Http::put(std::string url)
|
||||
Http Http::put2(std::string url)
|
||||
{
|
||||
Http http{ std::move(url) };
|
||||
http.p->method = "PUT";
|
||||
curl_easy_setopt(http.p->curl, CURLOPT_CUSTOMREQUEST, "PUT");
|
||||
return http;
|
||||
}
|
||||
@@ -786,6 +862,7 @@ Http Http::put2(std::string url)
|
||||
Http Http::patch(std::string url)
|
||||
{
|
||||
Http http{ std::move(url) };
|
||||
http.p->method = "PATCH";
|
||||
curl_easy_setopt(http.p->curl, CURLOPT_CUSTOMREQUEST, "PATCH");
|
||||
return http;
|
||||
}
|
||||
@@ -793,6 +870,7 @@ Http Http::patch(std::string url)
|
||||
Http Http::del(std::string url)
|
||||
{
|
||||
Http http{ std::move(url) };
|
||||
http.p->method = "DELETE";
|
||||
curl_easy_setopt(http.p->curl, CURLOPT_CUSTOMREQUEST, "DELETE");
|
||||
return http;
|
||||
}
|
||||
|
||||
@@ -183,6 +183,9 @@ public:
|
||||
// Cancels a request in progress
|
||||
void cancel();
|
||||
|
||||
// Print the request as a curl command for debugging
|
||||
void print() const;
|
||||
|
||||
// Tells whether current backend supports seting up a CA file using ca_file()
|
||||
static bool ca_file_supported();
|
||||
|
||||
|
||||
477
src/slic3r/Utils/ICloudServiceAgent.hpp
Normal file
477
src/slic3r/Utils/ICloudServiceAgent.hpp
Normal file
@@ -0,0 +1,477 @@
|
||||
#ifndef __I_CLOUD_SERVICE_AGENT_HPP__
|
||||
#define __I_CLOUD_SERVICE_AGENT_HPP__
|
||||
|
||||
#include "bambu_networking.hpp"
|
||||
#include "../../libslic3r/ProjectTask.hpp"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
/**
|
||||
* ICloudServiceAgent - Interface for authentication and cloud service operations.
|
||||
*
|
||||
* This interface encapsulates all cloud-related functionality including authentication:
|
||||
* - Lifecycle methods for agent initialization
|
||||
* - User session management (login/logout)
|
||||
* - Token access for dependent agents (IPrinterAgent)
|
||||
* - Login UI command builders for WebView integration
|
||||
* - Server connectivity and subscription management
|
||||
* - Settings synchronization (presets upload/download)
|
||||
* - Cloud user services (messages, tasks, firmware)
|
||||
* - Model mall and publishing
|
||||
* - Analytics and telemetry
|
||||
* - Ratings and reviews
|
||||
*
|
||||
* Implementations:
|
||||
* - OrcaCloudServiceAgent: Native implementation for Orca Cloud (includes OAuth PKCE)
|
||||
* - BBLCloudServiceAgent: Wrapper around Bambu Lab's proprietary DLL
|
||||
*
|
||||
* Token Sharing Pattern:
|
||||
* IPrinterAgent receives an ICloudServiceAgent instance via set_cloud_agent() to
|
||||
* access tokens for cloud-relay operations without coupling to a specific auth
|
||||
* implementation.
|
||||
*/
|
||||
class ICloudServiceAgent {
|
||||
public:
|
||||
virtual ~ICloudServiceAgent() = default;
|
||||
|
||||
// ========================================================================
|
||||
// Lifecycle Methods
|
||||
// ========================================================================
|
||||
/**
|
||||
* Initialize the logging backend for the agent.
|
||||
* Call after set_config_dir() so logs have a destination.
|
||||
*/
|
||||
virtual int init_log() = 0;
|
||||
|
||||
/**
|
||||
* Provide the writable configuration directory for storing auth state.
|
||||
* Must be called before start().
|
||||
*/
|
||||
virtual int set_config_dir(std::string config_dir) = 0;
|
||||
|
||||
/**
|
||||
* Register the client certificate file for TLS authentication.
|
||||
* May be unused by some implementations (e.g., OrcaCloudServiceAgent).
|
||||
*/
|
||||
virtual int set_cert_file(std::string folder, std::string filename) = 0;
|
||||
|
||||
/**
|
||||
* Set the country code for region-specific backend selection.
|
||||
*/
|
||||
virtual int set_country_code(std::string country_code) = 0;
|
||||
|
||||
/**
|
||||
* Start the agent, performing any expensive initialization.
|
||||
* Typically regenerates PKCE bundles and attempts silent sign-in.
|
||||
*/
|
||||
virtual int start() = 0;
|
||||
|
||||
// ========================================================================
|
||||
// User Session Management
|
||||
// ========================================================================
|
||||
/**
|
||||
* Authenticate the user with the provided JSON payload.
|
||||
*
|
||||
* Supported formats:
|
||||
* 1. Traditional: {"username": "...", "password": "..."}
|
||||
* 2. WebView/OAuth: {"command": "user_login", "data": {...}}
|
||||
* 3. Token format: {"data": {"token": "...", "refresh_token": "...", "user": {...}}}
|
||||
*
|
||||
* On completion, invokes the registered OnUserLoginFn callback.
|
||||
*/
|
||||
virtual int change_user(std::string user_info) = 0;
|
||||
|
||||
/**
|
||||
* Check whether a valid authenticated session exists.
|
||||
*/
|
||||
virtual bool is_user_login() = 0;
|
||||
|
||||
/**
|
||||
* Terminate the current session.
|
||||
* @param request If true, also notify the backend to invalidate the session.
|
||||
*/
|
||||
virtual int user_logout(bool request = false) = 0;
|
||||
|
||||
/**
|
||||
* Return the backend-generated user ID for the current session.
|
||||
*/
|
||||
virtual std::string get_user_id() = 0;
|
||||
|
||||
/**
|
||||
* Return the display name for the current user.
|
||||
*/
|
||||
virtual std::string get_user_name() = 0;
|
||||
|
||||
/**
|
||||
* Return the avatar URL/path for the current user.
|
||||
*/
|
||||
virtual std::string get_user_avatar() = 0;
|
||||
|
||||
/**
|
||||
* Return the nickname for the current user.
|
||||
*/
|
||||
virtual std::string get_user_nickname() = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Login UI Support
|
||||
// ========================================================================
|
||||
/**
|
||||
* Build a JSON command for the WebView login flow.
|
||||
* Contains backend URL, API key, and PKCE parameters.
|
||||
*/
|
||||
virtual std::string build_login_cmd() = 0;
|
||||
|
||||
/**
|
||||
* Build a JSON command for WebView logout.
|
||||
*/
|
||||
virtual std::string build_logout_cmd() = 0;
|
||||
|
||||
/**
|
||||
* Return a JSON snapshot of the active session (user info, no tokens).
|
||||
* Used by WebView to display current user state.
|
||||
*/
|
||||
virtual std::string build_login_info() = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Token Access (for dependent agents)
|
||||
// ========================================================================
|
||||
/**
|
||||
* Return the current access token for API calls.
|
||||
* Cloud and printer agents use this for Authorization headers.
|
||||
*/
|
||||
virtual std::string get_access_token() const = 0;
|
||||
|
||||
/**
|
||||
* Return the current refresh token (if available).
|
||||
*/
|
||||
virtual std::string get_refresh_token() const = 0;
|
||||
|
||||
/**
|
||||
* Ensure the access token is fresh, refreshing if necessary.
|
||||
* Call before making API requests to avoid 401 errors.
|
||||
*
|
||||
* @param reason Descriptive string for logging (e.g., "connect_server")
|
||||
* @return true if the token is fresh or was successfully refreshed
|
||||
*/
|
||||
virtual bool ensure_token_fresh(const std::string& reason) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Server Connectivity
|
||||
// ========================================================================
|
||||
/**
|
||||
* Return the base hostname for cloud API calls (varies by region).
|
||||
* Helpful for diagnostics and when building browser URLs.
|
||||
*/
|
||||
virtual std::string get_cloud_service_host() = 0;
|
||||
|
||||
/**
|
||||
* Return the login URL for the cloud service.
|
||||
* @param language Optional language code (e.g., "en-US", "zh-CN") for localized login page.
|
||||
* If empty, returns the default (non-localized) login URL.
|
||||
* @return The full URL to the login page, or a local file:// URL for native implementations.
|
||||
*/
|
||||
virtual std::string get_cloud_login_url(const std::string& language = "") = 0;
|
||||
|
||||
/**
|
||||
* Perform a health check against the configured backend.
|
||||
* Updates is_server_connected() state and triggers OnServerConnectedFn.
|
||||
*/
|
||||
virtual int connect_server() = 0;
|
||||
|
||||
/**
|
||||
* Return whether the server is currently reachable.
|
||||
*/
|
||||
virtual bool is_server_connected() = 0;
|
||||
|
||||
/**
|
||||
* Force a server state recheck, clearing any cached state.
|
||||
*/
|
||||
virtual int refresh_connection() = 0;
|
||||
|
||||
/**
|
||||
* Subscribe to a logical module (e.g., "printer", "user").
|
||||
*/
|
||||
virtual int start_subscribe(std::string module) = 0;
|
||||
|
||||
/**
|
||||
* Stop listening to a formerly subscribed module.
|
||||
*/
|
||||
virtual int stop_subscribe(std::string module) = 0;
|
||||
|
||||
/**
|
||||
* Subscribe to push streams for specific device identifiers.
|
||||
*/
|
||||
virtual int add_subscribe(std::vector<std::string> dev_list) = 0;
|
||||
|
||||
/**
|
||||
* Remove device-level subscriptions.
|
||||
*/
|
||||
virtual int del_subscribe(std::vector<std::string> dev_list) = 0;
|
||||
|
||||
/**
|
||||
* Enable or disable multi-machine mode.
|
||||
*/
|
||||
virtual void enable_multi_machine(bool enable) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Settings Synchronization
|
||||
// ========================================================================
|
||||
/**
|
||||
* Fetch all presets owned by the logged-in user.
|
||||
* @param user_presets Map populated with [type][setting_id] = json
|
||||
*/
|
||||
virtual int get_user_presets(std::map<std::string, std::map<std::string, std::string>>* user_presets) = 0;
|
||||
|
||||
/**
|
||||
* Request a new preset identifier from the server.
|
||||
*/
|
||||
virtual std::string request_setting_id(std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) = 0;
|
||||
|
||||
/**
|
||||
* Update or create a preset with a known setting_id.
|
||||
*/
|
||||
virtual int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) = 0;
|
||||
|
||||
/**
|
||||
* Trigger bulk download of user presets.
|
||||
*/
|
||||
virtual int get_setting_list(std::string bundle_version, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) = 0;
|
||||
|
||||
/**
|
||||
* Enhanced preset sync with per-item validation.
|
||||
*/
|
||||
virtual int get_setting_list2(std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) = 0;
|
||||
|
||||
/**
|
||||
* Delete a remote preset.
|
||||
*/
|
||||
virtual int delete_setting(std::string setting_id) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Cloud User Services
|
||||
// ========================================================================
|
||||
/**
|
||||
* Retrieve inbox/notification messages.
|
||||
*/
|
||||
virtual int get_my_message(int type, int after, int limit, unsigned int* http_code, std::string* http_body) = 0;
|
||||
|
||||
/**
|
||||
* Check for pending task reports.
|
||||
*/
|
||||
virtual int check_user_task_report(int* task_id, bool* printable) = 0;
|
||||
|
||||
/**
|
||||
* Fetch aggregated print statistics.
|
||||
*/
|
||||
virtual int get_user_print_info(unsigned int* http_code, std::string* http_body) = 0;
|
||||
|
||||
/**
|
||||
* Query user's tasks/prints.
|
||||
*/
|
||||
virtual int get_user_tasks(TaskQueryParams params, std::string* http_body) = 0;
|
||||
|
||||
/**
|
||||
* Fetch firmware information for a printer.
|
||||
*/
|
||||
virtual int get_printer_firmware(std::string dev_id, unsigned* http_code, std::string* http_body) = 0;
|
||||
|
||||
/**
|
||||
* Get plate index for a cloud task.
|
||||
*/
|
||||
virtual int get_task_plate_index(std::string task_id, int* plate_index) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve extended user profile info.
|
||||
*/
|
||||
virtual int get_user_info(int* identifier) = 0;
|
||||
|
||||
/**
|
||||
* Fetch subtask information.
|
||||
*/
|
||||
virtual int get_subtask_info(std::string subtask_id, std::string* task_json, unsigned int* http_code, std::string* http_body) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve slicing job info.
|
||||
*/
|
||||
virtual int get_slice_info(std::string project_id, std::string profile_id, int plate_index, std::string* slice_json) = 0;
|
||||
|
||||
/**
|
||||
* Query binding status for multiple devices.
|
||||
*/
|
||||
virtual int query_bind_status(std::vector<std::string> query_list, unsigned int* http_code, std::string* http_body) = 0;
|
||||
|
||||
/**
|
||||
* Update printer name in cloud profile.
|
||||
*/
|
||||
virtual int modify_printer_name(std::string dev_id, std::string dev_name) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Model Mall & Publishing
|
||||
// ========================================================================
|
||||
/**
|
||||
* Request live camera streaming URL.
|
||||
*/
|
||||
virtual int get_camera_url(std::string dev_id, std::function<void(std::string)> callback) = 0;
|
||||
|
||||
/**
|
||||
* Fetch staff-picked designs from model mall.
|
||||
*/
|
||||
virtual int get_design_staffpick(int offset, int limit, std::function<void(std::string)> callback) = 0;
|
||||
|
||||
/**
|
||||
* Run multi-stage publishing workflow.
|
||||
*/
|
||||
virtual int start_publish(PublishParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, std::string* out) = 0;
|
||||
|
||||
/**
|
||||
* Get model publish URL.
|
||||
*/
|
||||
virtual int get_model_publish_url(std::string* url) = 0;
|
||||
|
||||
/**
|
||||
* Fetch publishing subtask information.
|
||||
*/
|
||||
virtual int get_subtask(BBLModelTask* task, OnGetSubTaskFn getsub_fn) = 0;
|
||||
|
||||
/**
|
||||
* Get model mall home URL.
|
||||
*/
|
||||
virtual int get_model_mall_home_url(std::string* url) = 0;
|
||||
|
||||
/**
|
||||
* Build model detail page URL.
|
||||
*/
|
||||
virtual int get_model_mall_detail_url(std::string* url, std::string id) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve user's model mall profile.
|
||||
*/
|
||||
virtual int get_my_profile(std::string token, unsigned int* http_code, std::string* http_body) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Analytics & Tracking
|
||||
// ========================================================================
|
||||
/**
|
||||
* Enable/disable telemetry.
|
||||
*/
|
||||
virtual int track_enable(bool enable) = 0;
|
||||
|
||||
/**
|
||||
* Delete telemetry files.
|
||||
*/
|
||||
virtual int track_remove_files() = 0;
|
||||
|
||||
/**
|
||||
* Report a custom analytics event.
|
||||
*/
|
||||
virtual int track_event(std::string evt_key, std::string content) = 0;
|
||||
|
||||
/**
|
||||
* Set telemetry headers.
|
||||
*/
|
||||
virtual int track_header(std::string header) = 0;
|
||||
|
||||
/**
|
||||
* Update a tracked user property.
|
||||
*/
|
||||
virtual int track_update_property(std::string name, std::string value, std::string type = "string") = 0;
|
||||
|
||||
/**
|
||||
* Read a tracked user property.
|
||||
*/
|
||||
virtual int track_get_property(std::string name, std::string& value, std::string type = "string") = 0;
|
||||
|
||||
/**
|
||||
* Check if tracking is enabled.
|
||||
*/
|
||||
virtual bool get_track_enable() = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Ratings & Reviews
|
||||
// ========================================================================
|
||||
/**
|
||||
* Submit a review for a marketplace design.
|
||||
*/
|
||||
virtual int put_model_mall_rating(int design_id, int score, std::string content, std::vector<std::string> images, unsigned int& http_code, std::string& http_error) = 0;
|
||||
|
||||
/**
|
||||
* Get OSS configuration for image uploads.
|
||||
*/
|
||||
virtual int get_oss_config(std::string& config, std::string country_code, unsigned int& http_code, std::string& http_error) = 0;
|
||||
|
||||
/**
|
||||
* Upload rating images to OSS.
|
||||
*/
|
||||
virtual int put_rating_picture_oss(std::string& config, std::string& pic_oss_path, std::string model_id, int profile_id, unsigned int& http_code, std::string& http_error) = 0;
|
||||
|
||||
/**
|
||||
* Poll for rating result.
|
||||
*/
|
||||
virtual int get_model_mall_rating_result(int job_id, std::string& rating_result, unsigned int& http_code, std::string& http_error) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Extra Features
|
||||
// ========================================================================
|
||||
/**
|
||||
* Set additional HTTP headers for all requests.
|
||||
*/
|
||||
virtual int set_extra_http_header(std::map<std::string, std::string> extra_headers) = 0;
|
||||
|
||||
/**
|
||||
* Get the studio info URL.
|
||||
*/
|
||||
virtual std::string get_studio_info_url() = 0;
|
||||
|
||||
/**
|
||||
* Fetch MakerWorld user preferences.
|
||||
*/
|
||||
virtual int get_mw_user_preference(std::function<void(std::string)> callback) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve MakerWorld "For You" list.
|
||||
*/
|
||||
virtual int get_mw_user_4ulist(int seed, int limit, std::function<void(std::string)> callback) = 0;
|
||||
|
||||
/**
|
||||
* Return the version of the cloud service implementation.
|
||||
*/
|
||||
virtual std::string get_version() = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Callback Registration
|
||||
// ========================================================================
|
||||
/**
|
||||
* Register the login status callback.
|
||||
* Called after change_user() finishes or when the session expires.
|
||||
*/
|
||||
virtual int set_on_user_login_fn(OnUserLoginFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Register server connection status callback.
|
||||
*/
|
||||
virtual int set_on_server_connected_fn(OnServerConnectedFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Register HTTP error callback.
|
||||
*/
|
||||
virtual int set_on_http_error_fn(OnHttpErrorFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Provide country code getter callback.
|
||||
*/
|
||||
virtual int set_get_country_code_fn(GetCountryCodeFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Provide main thread queue callback.
|
||||
*/
|
||||
virtual int set_queue_on_main_fn(QueueOnMainFn fn) = 0;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // __I_CLOUD_SERVICE_AGENT_HPP__
|
||||
260
src/slic3r/Utils/IPrinterAgent.hpp
Normal file
260
src/slic3r/Utils/IPrinterAgent.hpp
Normal file
@@ -0,0 +1,260 @@
|
||||
#ifndef __I_PRINTER_AGENT_HPP__
|
||||
#define __I_PRINTER_AGENT_HPP__
|
||||
|
||||
#include "bambu_networking.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class ICloudServiceAgent;
|
||||
|
||||
/**
|
||||
* AgentInfo - Metadata structure for printer agent information.
|
||||
*
|
||||
* Contains identification and descriptive information about a printer agent
|
||||
* implementation, used for discovery and selection purposes.
|
||||
*/
|
||||
struct AgentInfo {
|
||||
std::string id; ///< Unique identifier for the agent, e.g. "orca", "bbl"
|
||||
std::string name; ///< Human-readable agent name, e.g. "Orca", "Bambu Lab"
|
||||
std::string version; ///< Agent version string, e.g. "1.0.0"
|
||||
std::string description; ///< Brief description of the agent's capabilities, e.g. "Orca printer agent"
|
||||
};
|
||||
|
||||
/**
|
||||
* FilamentSyncMode - Modes for filament data synchronization.
|
||||
*
|
||||
* Defines how filament information is obtained from the printer:
|
||||
* - Subscription: Real-time push updates (e.g., MQTT subscriptions)
|
||||
* - Pull: On-demand fetch via REST API (blocking call)
|
||||
* - None: Filament sync unavailable
|
||||
*/
|
||||
enum class FilamentSyncMode {
|
||||
none = 0, ///< Filament synchronization not supported
|
||||
subscription, ///< Real-time push updates via subscription (e.g., MQTT)
|
||||
pull ///< On-demand fetch via REST API (blocking call)
|
||||
};
|
||||
|
||||
/**
|
||||
* IPrinterAgent - Interface for printer operations.
|
||||
*
|
||||
* This interface encapsulates all printer-related functionality:
|
||||
* - Direct printer communication (LAN and cloud relay)
|
||||
* - Certificate management
|
||||
* - Device discovery (SSDP)
|
||||
* - Printer binding/unbinding
|
||||
* - Print job operations
|
||||
*
|
||||
* Implementations:
|
||||
* - OrcaPrinterAgent: Stub implementation (printer ops not yet supported)
|
||||
* - BBLPrinterAgent: Wrapper around Bambu Lab's proprietary DLL
|
||||
*
|
||||
* Token Access:
|
||||
* Printer agents receive an ICloudServiceAgent instance via set_cloud_agent() to
|
||||
* access tokens for cloud-relay operations.
|
||||
*/
|
||||
|
||||
class IPrinterAgent {
|
||||
public:
|
||||
virtual ~IPrinterAgent() = default;
|
||||
|
||||
// ========================================================================
|
||||
// Cloud Agent Dependency
|
||||
// ========================================================================
|
||||
/**
|
||||
* Set the cloud agent used for token access.
|
||||
* Must be called before any cloud-relay operations.
|
||||
*/
|
||||
virtual void set_cloud_agent(std::shared_ptr<ICloudServiceAgent> cloud) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Communication
|
||||
// ========================================================================
|
||||
/**
|
||||
* Publish a JSON command to a printer through cloud relay.
|
||||
*/
|
||||
virtual int send_message(std::string dev_id, std::string json_str, int qos, int flag) = 0;
|
||||
|
||||
/**
|
||||
* Establish a direct LAN connection to a printer.
|
||||
*/
|
||||
virtual int connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl) = 0;
|
||||
|
||||
/**
|
||||
* Tear down the active LAN printer connection.
|
||||
*/
|
||||
virtual int disconnect_printer() = 0;
|
||||
|
||||
/**
|
||||
* Send a JSON command to a LAN printer (bypassing cloud).
|
||||
*/
|
||||
virtual int send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Certificates
|
||||
// ========================================================================
|
||||
/**
|
||||
* Validate current user certificates for the printer.
|
||||
*/
|
||||
virtual int check_cert() = 0;
|
||||
|
||||
/**
|
||||
* Install or refresh device certificate for LAN TLS.
|
||||
*/
|
||||
virtual void install_device_cert(std::string dev_id, bool lan_only) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Discovery
|
||||
// ========================================================================
|
||||
/**
|
||||
* Start or stop SSDP discovery.
|
||||
*/
|
||||
virtual bool start_discovery(bool start, bool sending) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Binding
|
||||
// ========================================================================
|
||||
/**
|
||||
* Ping the binding endpoint to check printer readiness.
|
||||
*/
|
||||
virtual int ping_bind(std::string ping_code) = 0;
|
||||
|
||||
/**
|
||||
* Perform binding detection/handshake on a LAN printer.
|
||||
*/
|
||||
virtual int bind_detect(std::string dev_ip, std::string sec_link, detectResult& detect) = 0;
|
||||
|
||||
/**
|
||||
* Execute the multi-stage printer binding workflow.
|
||||
*/
|
||||
virtual int bind(std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn) = 0;
|
||||
|
||||
/**
|
||||
* Remove the association between account and printer.
|
||||
*/
|
||||
virtual int unbind(std::string dev_id) = 0;
|
||||
|
||||
/**
|
||||
* Request a one-time bind ticket from the server.
|
||||
*/
|
||||
virtual int request_bind_ticket(std::string* ticket) = 0;
|
||||
|
||||
/**
|
||||
* Register callback for fatal HTTP errors.
|
||||
*/
|
||||
virtual int set_server_callback(OnServerErrFn fn) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Machine Selection
|
||||
// ========================================================================
|
||||
/**
|
||||
* Return the currently selected printer ID.
|
||||
*/
|
||||
virtual std::string get_user_selected_machine() = 0;
|
||||
|
||||
/**
|
||||
* Update the selected machine preference.
|
||||
*/
|
||||
virtual int set_user_selected_machine(std::string dev_id) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Print Job Operations
|
||||
// ========================================================================
|
||||
/**
|
||||
* Start a fully managed cloud print.
|
||||
*/
|
||||
virtual int start_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) = 0;
|
||||
|
||||
/**
|
||||
* Start a local print with cloud record.
|
||||
*/
|
||||
virtual int start_local_print_with_record(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) = 0;
|
||||
|
||||
/**
|
||||
* Upload gcode to printer's SD card without starting.
|
||||
*/
|
||||
virtual int start_send_gcode_to_sdcard(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) = 0;
|
||||
|
||||
/**
|
||||
* Start a LAN-only print.
|
||||
*/
|
||||
virtual int start_local_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn) = 0;
|
||||
|
||||
/**
|
||||
* Start a print from printer's SD card.
|
||||
*/
|
||||
virtual int start_sdcard_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn) = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Callback Registration
|
||||
// ========================================================================
|
||||
/**
|
||||
* Register SSDP discovery callback.
|
||||
*/
|
||||
virtual int set_on_ssdp_msg_fn(OnMsgArrivedFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Register printer MQTT connection callback.
|
||||
*/
|
||||
virtual int set_on_printer_connected_fn(OnPrinterConnectedFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Register subscription failure callback.
|
||||
*/
|
||||
virtual int set_on_subscribe_failure_fn(GetSubscribeFailureFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Register cloud device message callback.
|
||||
*/
|
||||
virtual int set_on_message_fn(OnMessageFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Register user-scoped message callback.
|
||||
*/
|
||||
virtual int set_on_user_message_fn(OnMessageFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Register LAN connection status callback.
|
||||
*/
|
||||
virtual int set_on_local_connect_fn(OnLocalConnectedFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Register LAN message callback.
|
||||
*/
|
||||
virtual int set_on_local_message_fn(OnMessageFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Provide main thread queue callback.
|
||||
*/
|
||||
virtual int set_queue_on_main_fn(QueueOnMainFn fn) = 0;
|
||||
|
||||
/**
|
||||
* Get agent information.
|
||||
*/
|
||||
virtual AgentInfo get_agent_info() = 0;
|
||||
|
||||
// ========================================================================
|
||||
// Filament Operations
|
||||
// ========================================================================
|
||||
/**
|
||||
* Get the filament synchronization mode for this agent.
|
||||
*
|
||||
* @return FilamentSyncMode indicating how filament data is obtained:
|
||||
* - subscription: Real-time push updates via MQTT (no fetch needed)
|
||||
* - pull: On-demand fetch via REST API (call fetch_filament_info())
|
||||
* - none: Filament synchronization not supported
|
||||
*/
|
||||
virtual FilamentSyncMode get_filament_sync_mode() const { return FilamentSyncMode::none; }
|
||||
|
||||
/**
|
||||
* Refresh filament info from the printer synchronously.
|
||||
* Should only be called when get_filament_sync_mode() returns FilamentSyncMode::pull.
|
||||
* Populates the MachineObject's DevFilaSystem with fetched filament data.
|
||||
*/
|
||||
virtual void fetch_filament_info(std::string dev_id) {}
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // __I_PRINTER_AGENT_HPP__
|
||||
2031
src/slic3r/Utils/MoonrakerPrinterAgent.cpp
Normal file
2031
src/slic3r/Utils/MoonrakerPrinterAgent.cpp
Normal file
File diff suppressed because it is too large
Load Diff
182
src/slic3r/Utils/MoonrakerPrinterAgent.hpp
Normal file
182
src/slic3r/Utils/MoonrakerPrinterAgent.hpp
Normal file
@@ -0,0 +1,182 @@
|
||||
#ifndef __MOONRAKER_PRINTER_AGENT_HPP__
|
||||
#define __MOONRAKER_PRINTER_AGENT_HPP__
|
||||
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "ICloudServiceAgent.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class MoonrakerPrinterAgent final : public IPrinterAgent
|
||||
{
|
||||
public:
|
||||
explicit MoonrakerPrinterAgent(std::string log_dir);
|
||||
~MoonrakerPrinterAgent() override;
|
||||
|
||||
static AgentInfo get_agent_info_static();
|
||||
AgentInfo get_agent_info() override { return get_agent_info_static(); }
|
||||
|
||||
// Cloud Agent Dependency
|
||||
void set_cloud_agent(std::shared_ptr<ICloudServiceAgent> cloud) override;
|
||||
|
||||
// Communication
|
||||
int send_message(std::string dev_id, std::string json_str, int qos, int flag) override;
|
||||
int connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl) override;
|
||||
int disconnect_printer() override;
|
||||
int send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag) override;
|
||||
|
||||
// Certificates
|
||||
int check_cert() override;
|
||||
void install_device_cert(std::string dev_id, bool lan_only) override;
|
||||
|
||||
// Discovery
|
||||
bool start_discovery(bool start, bool sending) override;
|
||||
|
||||
// Binding
|
||||
int ping_bind(std::string ping_code) override;
|
||||
int bind_detect(std::string dev_ip, std::string sec_link, detectResult& detect) override;
|
||||
int bind(std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn) override;
|
||||
int unbind(std::string dev_id) override;
|
||||
int request_bind_ticket(std::string* ticket) override;
|
||||
int set_server_callback(OnServerErrFn fn) override;
|
||||
|
||||
// Machine Selection
|
||||
std::string get_user_selected_machine() override;
|
||||
int set_user_selected_machine(std::string dev_id) override;
|
||||
|
||||
// Print Job Operations
|
||||
int start_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) override;
|
||||
int start_local_print_with_record(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) override;
|
||||
int start_send_gcode_to_sdcard(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) override;
|
||||
int start_local_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn) override;
|
||||
int start_sdcard_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn) override;
|
||||
|
||||
// Callbacks
|
||||
int set_on_ssdp_msg_fn(OnMsgArrivedFn fn) override;
|
||||
int set_on_printer_connected_fn(OnPrinterConnectedFn fn) override;
|
||||
int set_on_subscribe_failure_fn(GetSubscribeFailureFn fn) override;
|
||||
int set_on_message_fn(OnMessageFn fn) override;
|
||||
int set_on_user_message_fn(OnMessageFn fn) override;
|
||||
int set_on_local_connect_fn(OnLocalConnectedFn fn) override;
|
||||
int set_on_local_message_fn(OnMessageFn fn) override;
|
||||
int set_queue_on_main_fn(QueueOnMainFn fn) override;
|
||||
|
||||
// Pull-mode agent (on-demand filament sync)
|
||||
FilamentSyncMode get_filament_sync_mode() const override { return FilamentSyncMode::pull; }
|
||||
void fetch_filament_info(std::string dev_id) override;
|
||||
|
||||
private:
|
||||
struct PrinthostConfig
|
||||
{
|
||||
std::string host;
|
||||
std::string port;
|
||||
std::string api_key;
|
||||
std::string base_url;
|
||||
std::string model_name;
|
||||
};
|
||||
|
||||
struct MoonrakerDeviceInfo
|
||||
{
|
||||
std::string dev_id;
|
||||
std::string dev_name;
|
||||
std::string version;
|
||||
};
|
||||
|
||||
int handle_request(const std::string& dev_id, const std::string& json_str);
|
||||
int send_version_info(const std::string& dev_id);
|
||||
int send_access_code(const std::string& dev_id);
|
||||
|
||||
bool get_printhost_config(PrinthostConfig& config) const;
|
||||
bool fetch_device_info(const std::string& base_url, const std::string& api_key, MoonrakerDeviceInfo& info, std::string& error) const;
|
||||
bool fetch_server_info(const std::string& base_url, const std::string& api_key, std::string& version, std::string& error) const;
|
||||
bool fetch_object_list(const std::string& base_url, const std::string& api_key, std::set<std::string>& objects, std::string& error) const;
|
||||
bool query_printer_status(const std::string& base_url, const std::string& api_key, nlohmann::json& status, std::string& error) const;
|
||||
bool send_gcode(const std::string& dev_id, const std::string& gcode) const;
|
||||
|
||||
std::string resolve_host(const std::string& dev_id) const;
|
||||
std::string resolve_api_key(const std::string& dev_id, const std::string& fallback) const;
|
||||
void store_host(const std::string& dev_id, const std::string& host, const std::string& api_key);
|
||||
|
||||
void announce_printhost_device();
|
||||
void dispatch_local_connect(int state, const std::string& dev_id, const std::string& msg);
|
||||
void dispatch_printer_connected(const std::string& dev_id);
|
||||
void dispatch_message(const std::string& dev_id, const std::string& payload);
|
||||
void start_status_stream(const std::string& dev_id, const std::string& base_url, const std::string& api_key);
|
||||
void stop_status_stream();
|
||||
void run_status_stream(std::string dev_id, std::string base_url, std::string api_key);
|
||||
void handle_ws_message(const std::string& dev_id, const std::string& payload);
|
||||
void update_status_cache(const nlohmann::json& updates);
|
||||
nlohmann::json build_print_payload_locked() const;
|
||||
|
||||
// Print control helpers
|
||||
int pause_print(const std::string& dev_id);
|
||||
int resume_print(const std::string& dev_id);
|
||||
int cancel_print(const std::string& dev_id);
|
||||
|
||||
// File upload
|
||||
bool upload_gcode(const std::string& local_path, const std::string& filename,
|
||||
const std::string& base_url, const std::string& api_key,
|
||||
OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
|
||||
|
||||
// JSON-RPC helper
|
||||
bool send_jsonrpc_command(const std::string& base_url, const std::string& api_key,
|
||||
const nlohmann::json& request, std::string& response) const;
|
||||
|
||||
// Server info (returns JSON, not just version string)
|
||||
bool fetch_server_info_json(const std::string& base_url, const std::string& api_key,
|
||||
nlohmann::json& info, std::string& error) const;
|
||||
|
||||
// Connection thread management
|
||||
void perform_connection_async(const std::string& dev_id,
|
||||
const std::string& base_url,
|
||||
const std::string& api_key);
|
||||
void finish_connection();
|
||||
|
||||
mutable std::recursive_mutex state_mutex;
|
||||
std::map<std::string, std::string> host_by_device;
|
||||
std::map<std::string, std::string> api_key_by_device;
|
||||
std::string ssdp_announced_host;
|
||||
std::string ssdp_announced_id;
|
||||
std::shared_ptr<ICloudServiceAgent> m_cloud_agent;
|
||||
std::string selected_machine;
|
||||
|
||||
OnMsgArrivedFn on_ssdp_msg_fn;
|
||||
OnPrinterConnectedFn on_printer_connected_fn;
|
||||
GetSubscribeFailureFn on_subscribe_failure_fn;
|
||||
OnMessageFn on_message_fn;
|
||||
OnMessageFn on_user_message_fn;
|
||||
OnLocalConnectedFn on_local_connect_fn;
|
||||
OnMessageFn on_local_message_fn;
|
||||
QueueOnMainFn queue_on_main_fn;
|
||||
OnServerErrFn on_server_err_fn;
|
||||
|
||||
mutable std::recursive_mutex payload_mutex;
|
||||
nlohmann::json status_cache;
|
||||
|
||||
std::atomic<int> next_jsonrpc_id{1};
|
||||
std::set<std::string> available_objects; // Track for feature detection
|
||||
|
||||
std::atomic<bool> ws_stop{false};
|
||||
std::atomic<bool> ws_reconnect_requested{false}; // Flag to trigger reconnection
|
||||
std::atomic<uint64_t> ws_last_emit_ms{0};
|
||||
std::thread ws_thread;
|
||||
|
||||
// Connection thread management
|
||||
std::atomic<bool> connect_in_progress{false};
|
||||
std::atomic<bool> connect_stop_requested{false};
|
||||
std::thread connect_thread;
|
||||
std::recursive_mutex connect_mutex;
|
||||
std::condition_variable connect_cv;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,118 +3,22 @@
|
||||
|
||||
#include "bambu_networking.hpp"
|
||||
#include "libslic3r/ProjectTask.hpp"
|
||||
#include "ICloudServiceAgent.hpp"
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include <memory>
|
||||
|
||||
using namespace BBL;
|
||||
|
||||
namespace Slic3r {
|
||||
typedef bool (*func_check_debug_consistent)(bool is_debug);
|
||||
typedef std::string (*func_get_version)(void);
|
||||
typedef void* (*func_create_agent)(std::string log_dir);
|
||||
typedef int (*func_destroy_agent)(void *agent);
|
||||
typedef int (*func_init_log)(void *agent);
|
||||
typedef int (*func_set_config_dir)(void *agent, std::string config_dir);
|
||||
typedef int (*func_set_cert_file)(void *agent, std::string folder, std::string filename);
|
||||
typedef int (*func_set_country_code)(void *agent, std::string country_code);
|
||||
typedef int (*func_start)(void *agent);
|
||||
typedef int (*func_set_on_ssdp_msg_fn)(void *agent, OnMsgArrivedFn fn);
|
||||
typedef int (*func_set_on_user_login_fn)(void *agent, OnUserLoginFn fn);
|
||||
typedef int (*func_set_on_printer_connected_fn)(void *agent, OnPrinterConnectedFn fn);
|
||||
typedef int (*func_set_on_server_connected_fn)(void *agent, OnServerConnectedFn fn);
|
||||
typedef int (*func_set_on_http_error_fn)(void *agent, OnHttpErrorFn fn);
|
||||
typedef int (*func_set_get_country_code_fn)(void *agent, GetCountryCodeFn fn);
|
||||
typedef int (*func_set_on_subscribe_failure_fn)(void *agent, GetSubscribeFailureFn fn);
|
||||
typedef int (*func_set_on_message_fn)(void *agent, OnMessageFn fn);
|
||||
typedef int (*func_set_on_user_message_fn)(void *agent, OnMessageFn fn);
|
||||
typedef int (*func_set_on_local_connect_fn)(void *agent, OnLocalConnectedFn fn);
|
||||
typedef int (*func_set_on_local_message_fn)(void *agent, OnMessageFn fn);
|
||||
typedef int (*func_set_queue_on_main_fn)(void *agent, QueueOnMainFn fn);
|
||||
typedef int (*func_connect_server)(void *agent);
|
||||
typedef bool (*func_is_server_connected)(void *agent);
|
||||
typedef int (*func_refresh_connection)(void *agent);
|
||||
typedef int (*func_start_subscribe)(void *agent, std::string module);
|
||||
typedef int (*func_stop_subscribe)(void *agent, std::string module);
|
||||
typedef int (*func_add_subscribe)(void *agent, std::vector<std::string> dev_list);
|
||||
typedef int (*func_del_subscribe)(void *agent, std::vector<std::string> dev_list);
|
||||
typedef void (*func_enable_multi_machine)(void *agent, bool enable);
|
||||
typedef int (*func_send_message)(void *agent, std::string dev_id, std::string json_str, int qos, int flag);
|
||||
typedef int (*func_connect_printer)(void *agent, std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl);
|
||||
typedef int (*func_disconnect_printer)(void *agent);
|
||||
typedef int (*func_send_message_to_printer)(void *agent, std::string dev_id, std::string json_str, int qos, int flag);
|
||||
typedef int (*func_check_cert)(void* agent);
|
||||
typedef void (*func_install_device_cert)(void* agent, std::string dev_id, bool lan_only);
|
||||
typedef bool (*func_start_discovery)(void *agent, bool start, bool sending);
|
||||
typedef int (*func_change_user)(void *agent, std::string user_info);
|
||||
typedef bool (*func_is_user_login)(void *agent);
|
||||
typedef int (*func_user_logout)(void *agent, bool request);
|
||||
typedef std::string (*func_get_user_id)(void *agent);
|
||||
typedef std::string (*func_get_user_name)(void *agent);
|
||||
typedef std::string (*func_get_user_avatar)(void *agent);
|
||||
typedef std::string (*func_get_user_nickanme)(void *agent);
|
||||
typedef std::string (*func_build_login_cmd)(void *agent);
|
||||
typedef std::string (*func_build_logout_cmd)(void *agent);
|
||||
typedef std::string (*func_build_login_info)(void *agent);
|
||||
typedef int (*func_ping_bind)(void *agent, std::string ping_code);
|
||||
typedef int (*func_bind_detect)(void *agent, std::string dev_ip, std::string sec_link, detectResult& detect);
|
||||
typedef int (*func_set_server_callback)(void *agent, OnServerErrFn fn);
|
||||
typedef int (*func_bind)(void *agent, std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn);
|
||||
typedef int (*func_unbind)(void *agent, std::string dev_id);
|
||||
typedef std::string (*func_get_bambulab_host)(void *agent);
|
||||
typedef std::string (*func_get_user_selected_machine)(void *agent);
|
||||
typedef int (*func_set_user_selected_machine)(void *agent, std::string dev_id);
|
||||
typedef int (*func_start_print)(void *agent, PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
|
||||
typedef int (*func_start_local_print_with_record)(void *agent, PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
|
||||
typedef int (*func_start_send_gcode_to_sdcard)(void *agent, PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
|
||||
typedef int (*func_start_local_print)(void *agent, PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
|
||||
typedef int (*func_start_sdcard_print)(void *agent, PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
|
||||
typedef int (*func_get_user_presets)(void *agent, std::map<std::string, std::map<std::string, std::string>>* user_presets);
|
||||
typedef std::string (*func_request_setting_id)(void *agent, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code);
|
||||
typedef int (*func_put_setting)(void *agent, std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code);
|
||||
typedef int (*func_get_setting_list)(void *agent, std::string bundle_version, ProgressFn pro_fn, WasCancelledFn cancel_fn);
|
||||
typedef int (*func_get_setting_list2)(void *agent, std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn, WasCancelledFn cancel_fn);
|
||||
typedef int (*func_delete_setting)(void *agent, std::string setting_id);
|
||||
typedef std::string (*func_get_studio_info_url)(void *agent);
|
||||
typedef int (*func_set_extra_http_header)(void *agent, std::map<std::string, std::string> extra_headers);
|
||||
typedef int (*func_get_my_message)(void *agent, int type, int after, int limit, unsigned int* http_code, std::string* http_body);
|
||||
typedef int (*func_check_user_task_report)(void *agent, int* task_id, bool* printable);
|
||||
typedef int (*func_get_user_print_info)(void *agent, unsigned int* http_code, std::string* http_body);
|
||||
typedef int (*func_get_user_tasks)(void *agent, TaskQueryParams params, std::string* http_body);
|
||||
typedef int (*func_get_printer_firmware)(void *agent, std::string dev_id, unsigned* http_code, std::string* http_body);
|
||||
typedef int (*func_get_task_plate_index)(void *agent, std::string task_id, int* plate_index);
|
||||
typedef int (*func_get_user_info)(void *agent, int* identifier);
|
||||
typedef int (*func_request_bind_ticket)(void *agent, std::string* ticket);
|
||||
typedef int (*func_get_subtask_info)(void *agent, std::string subtask_id, std::string* task_json, unsigned int* http_code, std::string *http_body);
|
||||
typedef int (*func_get_slice_info)(void *agent, std::string project_id, std::string profile_id, int plate_index, std::string* slice_json);
|
||||
typedef int (*func_query_bind_status)(void *agent, std::vector<std::string> query_list, unsigned int* http_code, std::string* http_body);
|
||||
typedef int (*func_modify_printer_name)(void *agent, std::string dev_id, std::string dev_name);
|
||||
typedef int (*func_get_camera_url)(void *agent, std::string dev_id, std::function<void(std::string)> callback);
|
||||
typedef int (*func_get_design_staffpick)(void *agent, int offset, int limit, std::function<void(std::string)> callback);
|
||||
typedef int (*func_start_pubilsh)(void *agent, PublishParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, std::string* out);
|
||||
typedef int (*func_get_model_publish_url)(void *agent, std::string* url);
|
||||
typedef int (*func_get_subtask)(void *agent, BBLModelTask* task, OnGetSubTaskFn getsub_fn);
|
||||
typedef int (*func_get_model_mall_home_url)(void *agent, std::string* url);
|
||||
typedef int (*func_get_model_mall_detail_url)(void *agent, std::string* url, std::string id);
|
||||
typedef int (*func_get_my_profile)(void *agent, std::string token, unsigned int *http_code, std::string *http_body);
|
||||
typedef int (*func_track_enable)(void *agent, bool enable);
|
||||
typedef int (*func_track_remove_files)(void *agent);
|
||||
typedef int (*func_track_event)(void *agent, std::string evt_key, std::string content);
|
||||
typedef int (*func_track_header)(void *agent, std::string header);
|
||||
typedef int (*func_track_update_property)(void *agent, std::string name, std::string value, std::string type);
|
||||
typedef int (*func_track_get_property)(void *agent, std::string name, std::string& value, std::string type);
|
||||
typedef int (*func_put_model_mall_rating_url)(
|
||||
void *agent, int rating_id, int score, std::string content, std::vector<std::string> images, unsigned int &http_code, std::string &http_error);
|
||||
typedef int (*func_get_oss_config)(void *agent, std::string &config, std::string country_code, unsigned int &http_code, std::string &http_error);
|
||||
typedef int (*func_put_rating_picture_oss)(
|
||||
void *agent, std::string &config, std::string &pic_oss_path, std::string model_id, int profile_id, unsigned int &http_code, std::string &http_error);
|
||||
typedef int (*func_get_model_mall_rating_result)(void *agent, int job_id, std::string &rating_result, unsigned int &http_code, std::string &http_error);
|
||||
|
||||
typedef int (*func_get_mw_user_preference)(void *agent, std::function<void(std::string)> callback);
|
||||
typedef int (*func_get_mw_user_4ulist)(void *agent, int seed, int limit, std::function<void(std::string)> callback);
|
||||
// Forward declaration
|
||||
class BBLNetworkPlugin;
|
||||
|
||||
//the NetworkAgent class
|
||||
class NetworkAgent
|
||||
{
|
||||
|
||||
public:
|
||||
// Static utility methods - delegate to BBLNetworkPlugin
|
||||
static std::string get_libpath_in_current_directory(std::string library_name);
|
||||
static std::string get_versioned_library_path(const std::string& version);
|
||||
static bool versioned_library_exists(const std::string& version);
|
||||
@@ -136,9 +40,24 @@ public:
|
||||
static NetworkLibraryLoadError get_load_error();
|
||||
static void clear_load_error();
|
||||
static void set_load_error(const std::string& message, const std::string& technical_details, const std::string& attempted_path);
|
||||
|
||||
// Traditional constructor (uses BBL DLL via singleton)
|
||||
NetworkAgent(std::string log_dir);
|
||||
|
||||
// Sub-agent composition constructor (uses injected sub-agents)
|
||||
NetworkAgent(std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
std::shared_ptr<IPrinterAgent> printer_agent);
|
||||
|
||||
~NetworkAgent();
|
||||
|
||||
// Sub-agent accessors
|
||||
std::shared_ptr<ICloudServiceAgent> get_cloud_agent() const { return m_cloud_agent; }
|
||||
std::shared_ptr<IPrinterAgent> get_printer_agent() const { return m_printer_agent; }
|
||||
|
||||
// Set the printer agent (for dynamic agent switching)
|
||||
void set_printer_agent(std::shared_ptr<IPrinterAgent> printer_agent);
|
||||
|
||||
// Instance methods - delegate to sub-agents or BBLNetworkPlugin
|
||||
int init_log();
|
||||
int set_config_dir(std::string config_dir);
|
||||
int set_cert_file(std::string folder, std::string filename);
|
||||
@@ -177,7 +96,7 @@ public:
|
||||
std::string get_user_id();
|
||||
std::string get_user_name();
|
||||
std::string get_user_avatar();
|
||||
std::string get_user_nickanme();
|
||||
std::string get_user_nickname();
|
||||
std::string build_login_cmd();
|
||||
std::string build_logout_cmd();
|
||||
std::string build_login_info();
|
||||
@@ -186,7 +105,8 @@ public:
|
||||
int set_server_callback(OnServerErrFn fn);
|
||||
int bind(std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn);
|
||||
int unbind(std::string dev_id);
|
||||
std::string get_bambulab_host();
|
||||
std::string get_cloud_service_host();
|
||||
std::string get_cloud_login_url(const std::string& language = "");
|
||||
std::string get_user_selected_machine();
|
||||
int set_user_selected_machine(std::string dev_id);
|
||||
int start_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
|
||||
@@ -194,6 +114,8 @@ public:
|
||||
int start_send_gcode_to_sdcard(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn);
|
||||
int start_local_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
|
||||
int start_sdcard_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn);
|
||||
FilamentSyncMode get_filament_sync_mode() const;
|
||||
void fetch_filament_info(std::string dev_id);
|
||||
int get_user_presets(std::map<std::string, std::map<std::string, std::string>>* user_presets);
|
||||
std::string request_setting_id(std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code);
|
||||
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code);
|
||||
@@ -236,117 +158,36 @@ public:
|
||||
|
||||
int get_mw_user_preference(std::function<void(std::string)> callback);
|
||||
int get_mw_user_4ulist(int seed, int limit, std::function<void(std::string)> callback);
|
||||
void *get_network_agent() { return network_agent; }
|
||||
|
||||
// Get underlying agent handle from BBLNetworkPlugin
|
||||
void* get_network_agent();
|
||||
|
||||
private:
|
||||
struct PrinterCallbacks {
|
||||
OnMsgArrivedFn on_ssdp_msg_fn = nullptr;
|
||||
OnPrinterConnectedFn on_printer_connected_fn = nullptr;
|
||||
GetSubscribeFailureFn on_subscribe_failure_fn = nullptr;
|
||||
OnMessageFn on_message_fn = nullptr;
|
||||
OnMessageFn on_user_message_fn = nullptr;
|
||||
OnLocalConnectedFn on_local_connect_fn = nullptr;
|
||||
OnMessageFn on_local_message_fn = nullptr;
|
||||
QueueOnMainFn queue_on_main_fn = nullptr;
|
||||
OnServerErrFn on_server_err_fn = nullptr;
|
||||
};
|
||||
|
||||
void apply_printer_callbacks(const std::shared_ptr<IPrinterAgent>& printer_agent,
|
||||
const PrinterCallbacks& callbacks);
|
||||
|
||||
mutable std::mutex m_agent_mutex; // Protect agent swapping
|
||||
PrinterCallbacks m_printer_callbacks;
|
||||
bool enable_track = false;
|
||||
void* network_agent { nullptr };
|
||||
|
||||
static NetworkLibraryLoadError s_load_error;
|
||||
|
||||
static func_check_debug_consistent check_debug_consistent_ptr;
|
||||
static func_get_version get_version_ptr;
|
||||
static func_create_agent create_agent_ptr;
|
||||
static func_destroy_agent destroy_agent_ptr;
|
||||
static func_init_log init_log_ptr;
|
||||
static func_set_config_dir set_config_dir_ptr;
|
||||
static func_set_cert_file set_cert_file_ptr;
|
||||
static func_set_country_code set_country_code_ptr;
|
||||
static func_start start_ptr;
|
||||
static func_set_on_ssdp_msg_fn set_on_ssdp_msg_fn_ptr;
|
||||
static func_set_on_user_login_fn set_on_user_login_fn_ptr;
|
||||
static func_set_on_printer_connected_fn set_on_printer_connected_fn_ptr;
|
||||
static func_set_on_server_connected_fn set_on_server_connected_fn_ptr;
|
||||
static func_set_on_http_error_fn set_on_http_error_fn_ptr;
|
||||
static func_set_get_country_code_fn set_get_country_code_fn_ptr;
|
||||
static func_set_on_subscribe_failure_fn set_on_subscribe_failure_fn_ptr;
|
||||
static func_set_on_message_fn set_on_message_fn_ptr;
|
||||
static func_set_on_user_message_fn set_on_user_message_fn_ptr;
|
||||
static func_set_on_local_connect_fn set_on_local_connect_fn_ptr;
|
||||
static func_set_on_local_message_fn set_on_local_message_fn_ptr;
|
||||
static func_set_queue_on_main_fn set_queue_on_main_fn_ptr;
|
||||
static func_connect_server connect_server_ptr;
|
||||
static func_is_server_connected is_server_connected_ptr;
|
||||
static func_refresh_connection refresh_connection_ptr;
|
||||
static func_start_subscribe start_subscribe_ptr;
|
||||
static func_stop_subscribe stop_subscribe_ptr;
|
||||
static func_add_subscribe add_subscribe_ptr;
|
||||
static func_del_subscribe del_subscribe_ptr;
|
||||
static func_enable_multi_machine enable_multi_machine_ptr;
|
||||
static func_send_message send_message_ptr;
|
||||
static func_connect_printer connect_printer_ptr;
|
||||
static func_disconnect_printer disconnect_printer_ptr;
|
||||
static func_send_message_to_printer send_message_to_printer_ptr;
|
||||
static func_check_cert check_cert_ptr;
|
||||
static func_install_device_cert install_device_cert_ptr;
|
||||
static func_start_discovery start_discovery_ptr;
|
||||
static func_change_user change_user_ptr;
|
||||
static func_is_user_login is_user_login_ptr;
|
||||
static func_user_logout user_logout_ptr;
|
||||
static func_get_user_id get_user_id_ptr;
|
||||
static func_get_user_name get_user_name_ptr;
|
||||
static func_get_user_avatar get_user_avatar_ptr;
|
||||
static func_get_user_nickanme get_user_nickanme_ptr;
|
||||
static func_build_login_cmd build_login_cmd_ptr;
|
||||
static func_build_logout_cmd build_logout_cmd_ptr;
|
||||
static func_build_login_info build_login_info_ptr;
|
||||
static func_ping_bind ping_bind_ptr;
|
||||
static func_bind_detect bind_detect_ptr;
|
||||
static func_set_server_callback set_server_callback_ptr;
|
||||
static func_bind bind_ptr;
|
||||
static func_unbind unbind_ptr;
|
||||
static func_get_bambulab_host get_bambulab_host_ptr;
|
||||
static func_get_user_selected_machine get_user_selected_machine_ptr;
|
||||
static func_set_user_selected_machine set_user_selected_machine_ptr;
|
||||
static func_start_print start_print_ptr;
|
||||
static func_start_local_print_with_record start_local_print_with_record_ptr;
|
||||
static func_start_send_gcode_to_sdcard start_send_gcode_to_sdcard_ptr;
|
||||
static func_start_local_print start_local_print_ptr;
|
||||
static func_start_sdcard_print start_sdcard_print_ptr;
|
||||
static func_get_user_presets get_user_presets_ptr;
|
||||
static func_request_setting_id request_setting_id_ptr;
|
||||
static func_put_setting put_setting_ptr;
|
||||
static func_get_setting_list get_setting_list_ptr;
|
||||
static func_get_setting_list2 get_setting_list2_ptr;
|
||||
static func_delete_setting delete_setting_ptr;
|
||||
static func_get_studio_info_url get_studio_info_url_ptr;
|
||||
static func_set_extra_http_header set_extra_http_header_ptr;
|
||||
static func_get_my_message get_my_message_ptr;
|
||||
static func_check_user_task_report check_user_task_report_ptr;
|
||||
static func_get_user_print_info get_user_print_info_ptr;
|
||||
static func_get_user_tasks get_user_tasks_ptr;
|
||||
static func_get_printer_firmware get_printer_firmware_ptr;
|
||||
static func_get_task_plate_index get_task_plate_index_ptr;
|
||||
static func_get_user_info get_user_info_ptr;
|
||||
static func_request_bind_ticket request_bind_ticket_ptr;
|
||||
static func_get_subtask_info get_subtask_info_ptr;
|
||||
static func_get_slice_info get_slice_info_ptr;
|
||||
static func_query_bind_status query_bind_status_ptr;
|
||||
static func_modify_printer_name modify_printer_name_ptr;
|
||||
static func_get_camera_url get_camera_url_ptr;
|
||||
static func_get_design_staffpick get_design_staffpick_ptr;
|
||||
static func_start_pubilsh start_publish_ptr;
|
||||
static func_get_model_publish_url get_model_publish_url_ptr;
|
||||
static func_get_subtask get_subtask_ptr;
|
||||
static func_get_model_mall_home_url get_model_mall_home_url_ptr;
|
||||
static func_get_model_mall_detail_url get_model_mall_detail_url_ptr;
|
||||
static func_get_my_profile get_my_profile_ptr;
|
||||
static func_track_enable track_enable_ptr;
|
||||
static func_track_remove_files track_remove_files_ptr;
|
||||
static func_track_event track_event_ptr;
|
||||
static func_track_header track_header_ptr;
|
||||
static func_track_update_property track_update_property_ptr;
|
||||
static func_track_get_property track_get_property_ptr;
|
||||
static func_put_model_mall_rating_url put_model_mall_rating_url_ptr;
|
||||
static func_get_oss_config get_oss_config_ptr;
|
||||
static func_put_rating_picture_oss put_rating_picture_oss_ptr;
|
||||
static func_get_model_mall_rating_result get_model_mall_rating_result_ptr;
|
||||
|
||||
static func_get_mw_user_preference get_mw_user_preference_ptr;
|
||||
static func_get_mw_user_4ulist get_mw_user_4ulist_ptr;
|
||||
// Sub-agent composition (for Orca/BBL mixed mode)
|
||||
std::shared_ptr<ICloudServiceAgent> m_cloud_agent;
|
||||
std::shared_ptr<IPrinterAgent> m_printer_agent;
|
||||
std::string m_printer_agent_id;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
176
src/slic3r/Utils/NetworkAgentFactory.cpp
Normal file
176
src/slic3r/Utils/NetworkAgentFactory.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
#include "NetworkAgentFactory.hpp"
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "ICloudServiceAgent.hpp"
|
||||
#include "BBLPrinterAgent.hpp"
|
||||
#include "OrcaPrinterAgent.hpp"
|
||||
#include "QidiPrinterAgent.hpp"
|
||||
#include "MoonrakerPrinterAgent.hpp"
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace {
|
||||
|
||||
static std::mutex s_registry_mutex;
|
||||
|
||||
std::map<std::string, PrinterAgentInfo>& get_printer_agents()
|
||||
{
|
||||
static std::map<std::string, PrinterAgentInfo> agents;
|
||||
return agents;
|
||||
}
|
||||
|
||||
std::string& get_default_agent_id()
|
||||
{
|
||||
static std::string default_id;
|
||||
return default_id;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool NetworkAgentFactory::register_printer_agent(const std::string& id, const std::string& display_name, PrinterAgentFactory factory)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
|
||||
auto result = agents.emplace(id, PrinterAgentInfo(id, display_name, std::move(factory)));
|
||||
|
||||
if (result.second) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Registered printer agent: " << id << " (" << display_name << ")";
|
||||
|
||||
// Set as default if it's the first agent registered
|
||||
auto& default_id = get_default_agent_id();
|
||||
if (default_id.empty()) {
|
||||
default_id = id;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer agent already registered: " << id;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkAgentFactory::is_printer_agent_registered(const std::string& id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
return agents.find(id) != agents.end();
|
||||
}
|
||||
|
||||
const PrinterAgentInfo* NetworkAgentFactory::get_printer_agent_info(const std::string& id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
auto it = agents.find(id);
|
||||
return (it != agents.end()) ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
std::vector<PrinterAgentInfo> NetworkAgentFactory::get_registered_printer_agents()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
std::vector<PrinterAgentInfo> result;
|
||||
result.reserve(agents.size());
|
||||
|
||||
for (const auto& pair : agents) {
|
||||
result.push_back(pair.second);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<IPrinterAgent> NetworkAgentFactory::create_printer_agent_by_id(const std::string& id,
|
||||
std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
const std::string& log_dir)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
auto it = agents.find(id);
|
||||
|
||||
if (it == agents.end()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Unknown printer agent ID: " << id;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second.factory(cloud_agent, log_dir);
|
||||
}
|
||||
|
||||
std::string NetworkAgentFactory::get_default_printer_agent_id()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
return get_default_agent_id();
|
||||
}
|
||||
|
||||
void NetworkAgentFactory::set_default_printer_agent_id(const std::string& id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
|
||||
if (agents.find(id) != agents.end()) {
|
||||
get_default_agent_id() = id;
|
||||
BOOST_LOG_TRIVIAL(info) << "Default printer agent set to: " << id;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Cannot set default to unregistered agent: " << id;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkAgentFactory::register_all_agents()
|
||||
{
|
||||
// Register Orca printer agent
|
||||
{
|
||||
auto info = OrcaPrinterAgent::get_agent_info_static();
|
||||
register_printer_agent(info.id, info.name,
|
||||
[](std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
const std::string& log_dir) -> std::shared_ptr<IPrinterAgent> {
|
||||
auto agent = std::make_shared<OrcaPrinterAgent>(log_dir);
|
||||
if (cloud_agent) {
|
||||
agent->set_cloud_agent(cloud_agent);
|
||||
}
|
||||
return agent;
|
||||
});
|
||||
}
|
||||
|
||||
// Register Qidi printer agent
|
||||
{
|
||||
auto info = QidiPrinterAgent::get_agent_info_static();
|
||||
register_printer_agent(info.id, info.name,
|
||||
[](std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
const std::string& log_dir) -> std::shared_ptr<IPrinterAgent> {
|
||||
auto agent = std::make_shared<QidiPrinterAgent>(log_dir);
|
||||
if (cloud_agent) {
|
||||
agent->set_cloud_agent(cloud_agent);
|
||||
}
|
||||
return agent;
|
||||
});
|
||||
}
|
||||
|
||||
// Register Moonraker printer agent
|
||||
{
|
||||
auto info = MoonrakerPrinterAgent::get_agent_info_static();
|
||||
register_printer_agent(info.id, info.name,
|
||||
[](std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
const std::string& log_dir) -> std::shared_ptr<IPrinterAgent> {
|
||||
auto agent = std::make_shared<MoonrakerPrinterAgent>(log_dir);
|
||||
if (cloud_agent) {
|
||||
agent->set_cloud_agent(cloud_agent);
|
||||
}
|
||||
return agent;
|
||||
});
|
||||
}
|
||||
|
||||
// Register BBL printer agent (only if bbl network agent is available)
|
||||
{
|
||||
auto info = BBLPrinterAgent::get_agent_info_static();
|
||||
register_printer_agent(info.id, info.name,
|
||||
[](std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
const std::string& log_dir) -> std::shared_ptr<IPrinterAgent> {
|
||||
auto agent = std::make_shared<BBLPrinterAgent>();
|
||||
if (cloud_agent) {
|
||||
agent->set_cloud_agent(cloud_agent);
|
||||
}
|
||||
return agent;
|
||||
});
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Registered " << get_printer_agents().size() << " printer agents";
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
250
src/slic3r/Utils/NetworkAgentFactory.hpp
Normal file
250
src/slic3r/Utils/NetworkAgentFactory.hpp
Normal file
@@ -0,0 +1,250 @@
|
||||
#ifndef __NETWORK_AGENT_FACTORY_HPP__
|
||||
#define __NETWORK_AGENT_FACTORY_HPP__
|
||||
|
||||
#include "ICloudServiceAgent.hpp"
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "NetworkAgent.hpp"
|
||||
#include "OrcaCloudServiceAgent.hpp"
|
||||
#include "BBLCloudServiceAgent.hpp"
|
||||
#include "BBLNetworkPlugin.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Forward declarations
|
||||
class ICloudServiceAgent;
|
||||
class IPrinterAgent;
|
||||
|
||||
/**
|
||||
* AgentProvider - Specifies which implementation to use for each agent type.
|
||||
*
|
||||
* - Orca: Native Orca implementations (OrcaCloudServiceAgent, OrcaPrinterAgent)
|
||||
* - BBL: BBL DLL wrapper implementations (BBLCloudServiceAgent, BBLPrinterAgent)
|
||||
*/
|
||||
enum class AgentProvider { Orca, BBL };
|
||||
|
||||
// Factory function type for creating printer agents
|
||||
using PrinterAgentFactory =
|
||||
std::function<std::shared_ptr<IPrinterAgent>(std::shared_ptr<ICloudServiceAgent> cloud_agent, const std::string& log_dir)>;
|
||||
|
||||
// Information about a registered printer agent
|
||||
struct PrinterAgentInfo
|
||||
{
|
||||
std::string id; // e.g., "orca", "bbl"
|
||||
std::string display_name; // e.g., "Orca Native", "Bambu Lab"
|
||||
PrinterAgentFactory factory; // Function to create the agent
|
||||
|
||||
PrinterAgentInfo(const std::string& id_, const std::string& display_name_, PrinterAgentFactory factory_)
|
||||
: id(id_), display_name(display_name_), factory(std::move(factory_))
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
* NetworkAgentFactory - Factory for creating network agent instances
|
||||
*
|
||||
* This factory creates cloud agents and printer agents for the networking subsystem.
|
||||
* The architecture separates cloud services (authentication, project sync) from
|
||||
* printer communication (device discovery, print jobs).
|
||||
*
|
||||
* Startup flow:
|
||||
* 1. Call register_all_agents() during app initialization
|
||||
* 2. Cloud agent created at startup via create_agent_from_config()
|
||||
* 3. Printer agent created on-demand when a printer is selected
|
||||
*
|
||||
* Usage:
|
||||
* // At app startup (before any agent creation)
|
||||
* NetworkAgentFactory::register_all_agents();
|
||||
*
|
||||
* // Create NetworkAgent with cloud agent only
|
||||
* auto agent = create_agent_from_config(log_dir, app_config);
|
||||
*
|
||||
* // When printer is selected - create printer agent from registry
|
||||
* auto printer = NetworkAgentFactory::create_printer_agent_by_id("orca", cloud, log_dir);
|
||||
*/
|
||||
class NetworkAgentFactory
|
||||
{
|
||||
public:
|
||||
// ========================================================================
|
||||
// Printer Agent Registry
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Register all built-in printer agents.
|
||||
* Must be called once during application initialization, before any
|
||||
* calls to get_registered_printer_agents() or create_printer_agent_by_id().
|
||||
*/
|
||||
static void register_all_agents();
|
||||
|
||||
/**
|
||||
* Register a printer agent type
|
||||
*
|
||||
* @param id Unique identifier for the agent (e.g., "orca", "bbl")
|
||||
* @param display_name Human-readable name for UI
|
||||
* @param factory Factory function to create the agent
|
||||
* @return true if registration succeeded, false if already registered
|
||||
*/
|
||||
static bool register_printer_agent(const std::string& id, const std::string& display_name, PrinterAgentFactory factory);
|
||||
|
||||
/**
|
||||
* Check if an agent ID is registered
|
||||
*/
|
||||
static bool is_printer_agent_registered(const std::string& id);
|
||||
|
||||
/**
|
||||
* Get info about a registered agent
|
||||
*/
|
||||
static const PrinterAgentInfo* get_printer_agent_info(const std::string& id);
|
||||
|
||||
/**
|
||||
* Get all registered printer agents (for UI population)
|
||||
*/
|
||||
static std::vector<PrinterAgentInfo> get_registered_printer_agents();
|
||||
|
||||
/**
|
||||
* Create a printer agent by ID (using registry)
|
||||
*
|
||||
* @param id Agent ID to create
|
||||
* @param cloud_agent Cloud agent for token access
|
||||
* @param log_dir Directory for log files
|
||||
* @return Shared pointer to IPrinterAgent, or nullptr if ID not found
|
||||
*/
|
||||
static std::shared_ptr<IPrinterAgent> create_printer_agent_by_id(const std::string& id,
|
||||
std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
const std::string& log_dir);
|
||||
|
||||
/**
|
||||
* Get default printer agent ID
|
||||
*/
|
||||
static std::string get_default_printer_agent_id();
|
||||
|
||||
/**
|
||||
* Set a specific agent as the default
|
||||
*/
|
||||
static void set_default_printer_agent_id(const std::string& id);
|
||||
|
||||
// ========================================================================
|
||||
// Cloud Agent Factory
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Create a cloud service agent based on provider type.
|
||||
* Handles authentication, project sync, and other cloud services.
|
||||
*
|
||||
* @param provider Which implementation to use (Orca or BBL)
|
||||
* @param log_dir Directory for log files
|
||||
* @return Shared pointer to ICloudServiceAgent implementation
|
||||
*/
|
||||
static std::shared_ptr<ICloudServiceAgent> create_cloud_agent(AgentProvider provider, const std::string& log_dir)
|
||||
{
|
||||
switch (provider) {
|
||||
case AgentProvider::Orca: return std::make_shared<OrcaCloudServiceAgent>(log_dir);
|
||||
case AgentProvider::BBL: {
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
if (!plugin.is_loaded()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!plugin.has_agent()) {
|
||||
plugin.create_agent(log_dir);
|
||||
}
|
||||
if (!plugin.has_agent()) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_shared<BBLCloudServiceAgent>();
|
||||
}
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// NetworkAgent Facade Creation
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Create a NetworkAgent from pre-created sub-agents
|
||||
*
|
||||
* @param cloud_agent Cloud service agent (required, includes auth)
|
||||
* @param printer_agent Printer agent (optional, can be nullptr)
|
||||
* @return Unique pointer to NetworkAgent facade
|
||||
*/
|
||||
static std::unique_ptr<NetworkAgent> create_from_agents(std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
std::shared_ptr<IPrinterAgent> printer_agent)
|
||||
{
|
||||
return std::make_unique<NetworkAgent>(std::move(cloud_agent), std::move(printer_agent));
|
||||
}
|
||||
|
||||
private:
|
||||
// Factory is not instantiable
|
||||
NetworkAgentFactory() = delete;
|
||||
~NetworkAgentFactory() = delete;
|
||||
NetworkAgentFactory(const NetworkAgentFactory&) = delete;
|
||||
NetworkAgentFactory& operator=(const NetworkAgentFactory&) = delete;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a NetworkAgent from AppConfig settings (main entry point)
|
||||
*
|
||||
* Creates a NetworkAgent with cloud agent only. The printer agent is created
|
||||
* separately when a printer is selected, via create_printer_agent_by_id().
|
||||
*
|
||||
* Cloud provider selection:
|
||||
* - use_orca_cloud=true → OrcaCloudServiceAgent (default)
|
||||
* - use_orca_cloud=false → BBLCloudServiceAgent (requires plugin)
|
||||
*
|
||||
* @param log_dir Directory for log files
|
||||
* @param app_config Application configuration object
|
||||
* @return NetworkAgent with cloud agent, or nullptr on failure
|
||||
*/
|
||||
inline std::unique_ptr<NetworkAgent> 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<OrcaCloudServiceAgent*>(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
|
||||
|
||||
#endif // __NETWORK_AGENT_FACTORY_HPP__
|
||||
2676
src/slic3r/Utils/OrcaCloudServiceAgent.cpp
Normal file
2676
src/slic3r/Utils/OrcaCloudServiceAgent.cpp
Normal file
File diff suppressed because it is too large
Load Diff
359
src/slic3r/Utils/OrcaCloudServiceAgent.hpp
Normal file
359
src/slic3r/Utils/OrcaCloudServiceAgent.hpp
Normal file
@@ -0,0 +1,359 @@
|
||||
#ifndef __ORCA_CLOUD_SERVICE_AGENT_HPP__
|
||||
#define __ORCA_CLOUD_SERVICE_AGENT_HPP__
|
||||
|
||||
#include "ICloudServiceAgent.hpp"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
class wxSecretStore;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Forward declaration
|
||||
class AppConfig;
|
||||
|
||||
// Constants for OAuth loopback server
|
||||
namespace auth_constants {
|
||||
constexpr int LOOPBACK_PORT = 41172;
|
||||
constexpr const char* LOOPBACK_PATH = "/callback";
|
||||
constexpr const char* TOKEN_PATH = "/auth/v1/token";
|
||||
constexpr const char* LOGOUT_PATH = "/auth/v1/logout";
|
||||
} // namespace auth_constants
|
||||
|
||||
// ============================================================================
|
||||
// Sync Protocol Data Structures (per Orca Cloud Sync Protocol Specification)
|
||||
// ============================================================================
|
||||
// Note: These may also be defined in OrcaNetwork.hpp - guards prevent redefinition
|
||||
|
||||
#ifndef ORCA_SYNC_STRUCTS_DEFINED
|
||||
#define ORCA_SYNC_STRUCTS_DEFINED
|
||||
|
||||
struct ProfileUpsert {
|
||||
std::string id;
|
||||
std::string name;
|
||||
nlohmann::json content;
|
||||
std::string updated_at;
|
||||
std::string created_at;
|
||||
};
|
||||
|
||||
struct SyncPullResponse {
|
||||
std::string next_cursor;
|
||||
std::vector<ProfileUpsert> upserts;
|
||||
std::vector<std::string> deletes;
|
||||
};
|
||||
|
||||
struct SyncPushResult {
|
||||
bool success;
|
||||
int http_code;
|
||||
std::string new_updated_at;
|
||||
ProfileUpsert server_version;
|
||||
bool server_deleted;
|
||||
std::string error_message;
|
||||
};
|
||||
|
||||
struct SyncState {
|
||||
std::string last_sync_timestamp;
|
||||
};
|
||||
|
||||
#endif // ORCA_SYNC_STRUCTS_DEFINED
|
||||
|
||||
/**
|
||||
* OrcaCloudServiceAgent - Native cloud service and authentication implementation for Orca Cloud.
|
||||
*
|
||||
* Implements the ICloudServiceAgent interface with:
|
||||
* - Full OAuth 2.0 PKCE authentication support
|
||||
* - Token storage via wxSecretStore with AES-256-GCM encrypted file fallback
|
||||
* - JWT expiry decoding and proactive token refresh
|
||||
* - Session management with thread-safe state access
|
||||
* - Settings synchronization (sync_pull, sync_push)
|
||||
* - Server connectivity management
|
||||
* - HTTP helpers with automatic token injection
|
||||
*
|
||||
* This class combines the functionality of the former OrcaAuthAgent and OrcaCloudServiceAgent.
|
||||
*/
|
||||
class OrcaCloudServiceAgent : public ICloudServiceAgent {
|
||||
public:
|
||||
// ========================================================================
|
||||
// Auth Session Types
|
||||
// ========================================================================
|
||||
struct SessionInfo {
|
||||
std::string access_token;
|
||||
std::string refresh_token;
|
||||
std::string user_id;
|
||||
std::string user_name;
|
||||
std::string user_nickname;
|
||||
std::string user_avatar;
|
||||
std::chrono::system_clock::time_point expires_at{};
|
||||
bool logged_in = false;
|
||||
};
|
||||
|
||||
struct PkceBundle {
|
||||
std::string verifier;
|
||||
std::string challenge;
|
||||
std::string state;
|
||||
std::string redirect;
|
||||
int loopback_port = auth_constants::LOOPBACK_PORT;
|
||||
};
|
||||
|
||||
using SessionHandler = std::function<bool(const std::string&)>;
|
||||
using OnLoginCompleteHandler = std::function<void(bool success, const std::string& user_id)>;
|
||||
|
||||
explicit OrcaCloudServiceAgent(std::string log_dir);
|
||||
~OrcaCloudServiceAgent() override;
|
||||
|
||||
// Configuration
|
||||
void configure_urls(AppConfig* app_config);
|
||||
void set_api_base_url(const std::string& url);
|
||||
void set_auth_base_url(const std::string& url);
|
||||
void set_use_encrypted_token_file(bool use);
|
||||
bool get_use_encrypted_token_file() const;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Lifecycle Methods
|
||||
// ========================================================================
|
||||
int init_log() override;
|
||||
int set_config_dir(std::string config_dir) override;
|
||||
int set_cert_file(std::string folder, std::string filename) override;
|
||||
int set_country_code(std::string country_code) override;
|
||||
int start() override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - User Session Management
|
||||
// ========================================================================
|
||||
int change_user(std::string user_info) override;
|
||||
bool is_user_login() override;
|
||||
int user_logout(bool request = false) override;
|
||||
std::string get_user_id() override;
|
||||
std::string get_user_name() override;
|
||||
std::string get_user_avatar() override;
|
||||
std::string get_user_nickname() override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Login UI Support
|
||||
// ========================================================================
|
||||
std::string build_login_cmd() override;
|
||||
std::string build_logout_cmd() override;
|
||||
std::string build_login_info() override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Token Access
|
||||
// ========================================================================
|
||||
std::string get_access_token() const override;
|
||||
std::string get_refresh_token() const override;
|
||||
bool ensure_token_fresh(const std::string& reason) override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Server Connectivity
|
||||
// ========================================================================
|
||||
std::string get_cloud_service_host() override;
|
||||
std::string get_cloud_login_url(const std::string& language = "") override;
|
||||
int connect_server() override;
|
||||
bool is_server_connected() override;
|
||||
int refresh_connection() override;
|
||||
int start_subscribe(std::string module) override;
|
||||
int stop_subscribe(std::string module) override;
|
||||
int add_subscribe(std::vector<std::string> dev_list) override;
|
||||
int del_subscribe(std::vector<std::string> dev_list) override;
|
||||
void enable_multi_machine(bool enable) override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Settings Synchronization
|
||||
// ========================================================================
|
||||
int get_user_presets(std::map<std::string, std::map<std::string, std::string>>* user_presets) override;
|
||||
std::string request_setting_id(std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
|
||||
int put_setting(std::string setting_id, std::string name, std::map<std::string, std::string>* values_map, unsigned int* http_code) override;
|
||||
int get_setting_list(std::string bundle_version, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
|
||||
int get_setting_list2(std::string bundle_version, CheckFn chk_fn, ProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr) override;
|
||||
int delete_setting(std::string setting_id) override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Cloud User Services
|
||||
// ========================================================================
|
||||
int get_my_message(int type, int after, int limit, unsigned int* http_code, std::string* http_body) override;
|
||||
int check_user_task_report(int* task_id, bool* printable) override;
|
||||
int get_user_print_info(unsigned int* http_code, std::string* http_body) override;
|
||||
int get_user_tasks(TaskQueryParams params, std::string* http_body) override;
|
||||
int get_printer_firmware(std::string dev_id, unsigned* http_code, std::string* http_body) override;
|
||||
int get_task_plate_index(std::string task_id, int* plate_index) override;
|
||||
int get_user_info(int* identifier) override;
|
||||
int get_subtask_info(std::string subtask_id, std::string* task_json, unsigned int* http_code, std::string* http_body) override;
|
||||
int get_slice_info(std::string project_id, std::string profile_id, int plate_index, std::string* slice_json) override;
|
||||
int query_bind_status(std::vector<std::string> query_list, unsigned int* http_code, std::string* http_body) override;
|
||||
int modify_printer_name(std::string dev_id, std::string dev_name) override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Model Mall & Publishing
|
||||
// ========================================================================
|
||||
int get_camera_url(std::string dev_id, std::function<void(std::string)> callback) override;
|
||||
int get_design_staffpick(int offset, int limit, std::function<void(std::string)> callback) override;
|
||||
int start_publish(PublishParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, std::string* out) override;
|
||||
int get_model_publish_url(std::string* url) override;
|
||||
int get_subtask(BBLModelTask* task, OnGetSubTaskFn getsub_fn) override;
|
||||
int get_model_mall_home_url(std::string* url) override;
|
||||
int get_model_mall_detail_url(std::string* url, std::string id) override;
|
||||
int get_my_profile(std::string token, unsigned int* http_code, std::string* http_body) override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Analytics & Tracking
|
||||
// ========================================================================
|
||||
int track_enable(bool enable) override;
|
||||
int track_remove_files() override;
|
||||
int track_event(std::string evt_key, std::string content) override;
|
||||
int track_header(std::string header) override;
|
||||
int track_update_property(std::string name, std::string value, std::string type = "string") override;
|
||||
int track_get_property(std::string name, std::string& value, std::string type = "string") override;
|
||||
bool get_track_enable() override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Ratings & Reviews
|
||||
// ========================================================================
|
||||
int put_model_mall_rating(int design_id, int score, std::string content, std::vector<std::string> images, unsigned int& http_code, std::string& http_error) override;
|
||||
int get_oss_config(std::string& config, std::string country_code, unsigned int& http_code, std::string& http_error) override;
|
||||
int put_rating_picture_oss(std::string& config, std::string& pic_oss_path, std::string model_id, int profile_id, unsigned int& http_code, std::string& http_error) override;
|
||||
int get_model_mall_rating_result(int job_id, std::string& rating_result, unsigned int& http_code, std::string& http_error) override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Extra Features
|
||||
// ========================================================================
|
||||
int set_extra_http_header(std::map<std::string, std::string> extra_headers) override;
|
||||
std::string get_studio_info_url() override;
|
||||
int get_mw_user_preference(std::function<void(std::string)> callback) override;
|
||||
int get_mw_user_4ulist(int seed, int limit, std::function<void(std::string)> callback) override;
|
||||
std::string get_version() override;
|
||||
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Callbacks
|
||||
// ========================================================================
|
||||
int set_on_user_login_fn(OnUserLoginFn fn) override;
|
||||
int set_on_server_connected_fn(OnServerConnectedFn fn) override;
|
||||
int set_on_http_error_fn(OnHttpErrorFn fn) override;
|
||||
int set_get_country_code_fn(GetCountryCodeFn fn) override;
|
||||
int set_queue_on_main_fn(QueueOnMainFn fn) override;
|
||||
|
||||
// Sync state management
|
||||
void load_sync_state();
|
||||
void save_sync_state();
|
||||
void clear_sync_state();
|
||||
const SyncState& get_sync_state() const { return sync_state; }
|
||||
|
||||
// ========================================================================
|
||||
// Additional Public Methods - Auth
|
||||
// ========================================================================
|
||||
void set_session_handler(SessionHandler handler);
|
||||
void set_on_login_complete_handler(OnLoginCompleteHandler handler);
|
||||
|
||||
const PkceBundle& pkce();
|
||||
void regenerate_pkce();
|
||||
|
||||
void persist_refresh_token(const std::string& token);
|
||||
bool load_refresh_token(std::string& out_token);
|
||||
void clear_refresh_token();
|
||||
|
||||
// Token refresh helpers
|
||||
bool refresh_if_expiring(std::chrono::seconds skew, const std::string& reason);
|
||||
bool refresh_from_storage(const std::string& reason, bool async = false);
|
||||
bool refresh_now(const std::string& refresh_token, const std::string& reason, bool async = false);
|
||||
bool refresh_session_with_token(const std::string& refresh_token);
|
||||
|
||||
// Session state helpers
|
||||
bool set_user_session(const std::string& token,
|
||||
const std::string& user_id,
|
||||
const std::string& username,
|
||||
const std::string& name,
|
||||
const std::string& nickname,
|
||||
const std::string& avatar,
|
||||
const std::string& refresh_token = "");
|
||||
void clear_session();
|
||||
|
||||
private:
|
||||
// Sync protocol helpers
|
||||
int sync_pull(
|
||||
std::function<void(const SyncPullResponse&)> on_success,
|
||||
std::function<void(int http_code, const std::string& error)> on_error
|
||||
);
|
||||
|
||||
SyncPushResult sync_push(
|
||||
const std::string& profile_id,
|
||||
const std::string& name,
|
||||
const nlohmann::json& content,
|
||||
const std::string& original_updated_at = ""
|
||||
);
|
||||
|
||||
// HTTP request helpers
|
||||
int http_get(const std::string& path, std::string* response_body, unsigned int* http_code);
|
||||
int http_post(const std::string& path, const std::string& body, std::string* response_body, unsigned int* http_code);
|
||||
int http_put(const std::string& path, const std::string& body, std::string* response_body, unsigned int* http_code);
|
||||
int http_delete(const std::string& path, std::string* response_body, unsigned int* http_code);
|
||||
std::map<std::string, std::string> data_headers();
|
||||
bool attempt_refresh_after_unauthorized(const std::string& reason);
|
||||
|
||||
// Auth HTTP helpers
|
||||
bool http_post_token(const std::string& body, std::string* response_body, unsigned int* http_code, const std::string& url = "");
|
||||
bool http_post_auth(const std::string& path, const std::string& body, std::string* response_body, unsigned int* http_code);
|
||||
bool exchange_auth_code(const std::string& auth_code, const std::string& state, std::string& session_payload);
|
||||
void update_redirect_uri();
|
||||
void compute_fallback_path();
|
||||
bool decode_jwt_expiry(const std::string& token, std::chrono::system_clock::time_point& out_tp);
|
||||
bool should_refresh_locked(std::chrono::seconds skew) const;
|
||||
void invoke_user_login_callback(int online_login, bool login);
|
||||
|
||||
// Callback invocation
|
||||
void invoke_server_connected_callback(int return_code, int reason_code);
|
||||
void invoke_http_error_callback(unsigned http_code, const std::string& http_body);
|
||||
|
||||
// JSON helpers
|
||||
std::string map_to_json(const std::map<std::string, std::string>& map);
|
||||
void json_to_map(const std::string& json, std::map<std::string, std::string>& map);
|
||||
|
||||
// Member variables - configuration
|
||||
std::string log_dir;
|
||||
std::string config_dir;
|
||||
std::string api_base_url;
|
||||
std::string auth_base_url;
|
||||
std::string country_code;
|
||||
std::map<std::string, std::string> extra_headers;
|
||||
std::map<std::string, std::string> auth_headers;
|
||||
mutable std::mutex headers_mutex;
|
||||
bool m_use_encrypted_token_file{false};
|
||||
|
||||
// Member variables - auth state
|
||||
PkceBundle pkce_bundle;
|
||||
std::string refresh_fallback_path;
|
||||
SessionHandler session_handler;
|
||||
OnLoginCompleteHandler on_login_complete_handler;
|
||||
SessionInfo session;
|
||||
mutable std::mutex session_mutex;
|
||||
|
||||
// Member variables - connection state
|
||||
bool is_connected{false};
|
||||
bool enable_track{false};
|
||||
bool multi_machine_enabled{false};
|
||||
|
||||
// Sync state
|
||||
SyncState sync_state;
|
||||
std::string sync_state_path;
|
||||
|
||||
// Callbacks
|
||||
OnUserLoginFn on_user_login_fn;
|
||||
OnServerConnectedFn on_server_connected_fn;
|
||||
OnHttpErrorFn on_http_error_fn;
|
||||
GetCountryCodeFn get_country_code_fn;
|
||||
QueueOnMainFn queue_on_main_fn;
|
||||
mutable std::mutex callback_mutex;
|
||||
|
||||
// Thread safety
|
||||
mutable std::recursive_mutex state_mutex;
|
||||
std::thread refresh_thread;
|
||||
std::atomic_bool refresh_running{false};
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // __ORCA_CLOUD_SERVICE_AGENT_HPP__
|
||||
245
src/slic3r/Utils/OrcaPrinterAgent.cpp
Normal file
245
src/slic3r/Utils/OrcaPrinterAgent.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
#include "OrcaPrinterAgent.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
const std::string OrcaPrinterAgent_VERSION = "0.0.1";
|
||||
|
||||
OrcaPrinterAgent::OrcaPrinterAgent(std::string log_dir) : log_dir(std::move(log_dir))
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "OrcaPrinterAgent: Constructor - log_dir=" << this->log_dir;
|
||||
}
|
||||
|
||||
OrcaPrinterAgent::~OrcaPrinterAgent() = default;
|
||||
|
||||
void OrcaPrinterAgent::set_cloud_agent(std::shared_ptr<ICloudServiceAgent> cloud)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
m_cloud_agent = cloud;
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: Cloud agent set";
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Communication - All Stubs
|
||||
// ============================================================================
|
||||
|
||||
int OrcaPrinterAgent::send_message(std::string dev_id, std::string json_str, int qos, int flag)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: send_message (stub) - dev_id=" << dev_id;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: connect_printer (stub) - dev_id=" << dev_id << ", dev_ip=" << dev_ip;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::disconnect_printer()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: disconnect_printer (stub)";
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: send_message_to_printer (stub) - dev_id=" << dev_id;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Certificates - All Stubs
|
||||
// ============================================================================
|
||||
|
||||
int OrcaPrinterAgent::check_cert()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: check_cert (stub)";
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
void OrcaPrinterAgent::install_device_cert(std::string dev_id, bool lan_only)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: install_device_cert (stub) - dev_id=" << dev_id;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Discovery - Stub
|
||||
// ============================================================================
|
||||
|
||||
bool OrcaPrinterAgent::start_discovery(bool start, bool sending)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: start_discovery (stub) - start=" << start << ", sending=" << sending;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Binding - All Stubs
|
||||
// ============================================================================
|
||||
|
||||
int OrcaPrinterAgent::ping_bind(std::string ping_code)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: ping_bind (stub) - ping_code=" << ping_code;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::bind_detect(std::string dev_ip, std::string sec_link, detectResult& detect)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: bind_detect (stub) - dev_ip=" << dev_ip;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::bind(
|
||||
std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: bind (stub) - dev_id=" << dev_id;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::unbind(std::string dev_id)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: unbind (stub) - dev_id=" << dev_id;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::request_bind_ticket(std::string* ticket)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: request_bind_ticket (stub)";
|
||||
if (ticket)
|
||||
*ticket = "";
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::set_server_callback(OnServerErrFn fn)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
on_server_err_fn = fn;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Machine Selection
|
||||
// ============================================================================
|
||||
|
||||
std::string OrcaPrinterAgent::get_user_selected_machine()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
return selected_machine;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::set_user_selected_machine(std::string dev_id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
selected_machine = dev_id;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Agent Information
|
||||
// ============================================================================
|
||||
AgentInfo OrcaPrinterAgent::get_agent_info_static()
|
||||
{
|
||||
return AgentInfo{.id = "orca",
|
||||
.name = "Orca Printer Agent",
|
||||
.version = OrcaPrinterAgent_VERSION,
|
||||
.description = "Orca Printer Communication Protocol Agent"};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Print Job Operations - All Stubs
|
||||
// ============================================================================
|
||||
|
||||
int OrcaPrinterAgent::start_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: start_print (stub) - task_name=" << params.task_name;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::start_local_print_with_record(PrintParams params,
|
||||
OnUpdateStatusFn update_fn,
|
||||
WasCancelledFn cancel_fn,
|
||||
OnWaitFn wait_fn)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: start_local_print_with_record (stub)";
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::start_send_gcode_to_sdcard(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: start_send_gcode_to_sdcard (stub)";
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::start_local_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: start_local_print (stub)";
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::start_sdcard_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaPrinterAgent: start_sdcard_print (stub)";
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Callback Registration
|
||||
// ============================================================================
|
||||
|
||||
int OrcaPrinterAgent::set_on_ssdp_msg_fn(OnMsgArrivedFn fn)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
on_ssdp_msg_fn = fn;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::set_on_printer_connected_fn(OnPrinterConnectedFn fn)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
on_printer_connected_fn = fn;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::set_on_subscribe_failure_fn(GetSubscribeFailureFn fn)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
on_subscribe_failure_fn = fn;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::set_on_message_fn(OnMessageFn fn)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
on_message_fn = fn;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::set_on_user_message_fn(OnMessageFn fn)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
on_user_message_fn = fn;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::set_on_local_connect_fn(OnLocalConnectedFn fn)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
on_local_connect_fn = fn;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::set_on_local_message_fn(OnMessageFn fn)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
on_local_message_fn = fn;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaPrinterAgent::set_queue_on_main_fn(QueueOnMainFn fn)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_mutex);
|
||||
queue_on_main_fn = fn;
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
100
src/slic3r/Utils/OrcaPrinterAgent.hpp
Normal file
100
src/slic3r/Utils/OrcaPrinterAgent.hpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#ifndef __ORCA_PRINTER_AGENT_HPP__
|
||||
#define __ORCA_PRINTER_AGENT_HPP__
|
||||
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "ICloudServiceAgent.hpp"
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
/**
|
||||
* OrcaPrinterAgent - Stub implementation for printer operations.
|
||||
*
|
||||
* All printer-related operations are currently stubs that return success.
|
||||
* Actual printer connectivity requires the BBL SDK or future Orca implementation.
|
||||
*/
|
||||
class OrcaPrinterAgent : public IPrinterAgent {
|
||||
public:
|
||||
explicit OrcaPrinterAgent(std::string log_dir);
|
||||
~OrcaPrinterAgent() override;
|
||||
|
||||
// ========================================================================
|
||||
// IPrinterAgent Interface Implementation
|
||||
// ========================================================================
|
||||
|
||||
void set_cloud_agent(std::shared_ptr<ICloudServiceAgent> cloud) override;
|
||||
|
||||
// Communication
|
||||
int send_message(std::string dev_id, std::string json_str, int qos, int flag) override;
|
||||
int connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl) override;
|
||||
int disconnect_printer() override;
|
||||
int send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag) override;
|
||||
|
||||
// Certificates
|
||||
int check_cert() override;
|
||||
void install_device_cert(std::string dev_id, bool lan_only) override;
|
||||
|
||||
// Discovery
|
||||
bool start_discovery(bool start, bool sending) override;
|
||||
|
||||
// Binding
|
||||
int ping_bind(std::string ping_code) override;
|
||||
int bind_detect(std::string dev_ip, std::string sec_link, detectResult& detect) override;
|
||||
int bind(std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn) override;
|
||||
int unbind(std::string dev_id) override;
|
||||
int request_bind_ticket(std::string* ticket) override;
|
||||
int set_server_callback(OnServerErrFn fn) override;
|
||||
|
||||
// Machine Selection
|
||||
std::string get_user_selected_machine() override;
|
||||
int set_user_selected_machine(std::string dev_id) override;
|
||||
|
||||
/**
|
||||
* Get agent information.
|
||||
*
|
||||
* @return AgentInfo struct containing agent identification and descriptive information
|
||||
*/
|
||||
static AgentInfo get_agent_info_static();
|
||||
AgentInfo get_agent_info() override { return get_agent_info_static(); }
|
||||
|
||||
// Print Job Operations
|
||||
int start_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) override;
|
||||
int start_local_print_with_record(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) override;
|
||||
int start_send_gcode_to_sdcard(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn) override;
|
||||
int start_local_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn) override;
|
||||
int start_sdcard_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn) override;
|
||||
|
||||
// Callbacks
|
||||
int set_on_ssdp_msg_fn(OnMsgArrivedFn fn) override;
|
||||
int set_on_printer_connected_fn(OnPrinterConnectedFn fn) override;
|
||||
int set_on_subscribe_failure_fn(GetSubscribeFailureFn fn) override;
|
||||
int set_on_message_fn(OnMessageFn fn) override;
|
||||
int set_on_user_message_fn(OnMessageFn fn) override;
|
||||
int set_on_local_connect_fn(OnLocalConnectedFn fn) override;
|
||||
int set_on_local_message_fn(OnMessageFn fn) override;
|
||||
int set_queue_on_main_fn(QueueOnMainFn fn) override;
|
||||
|
||||
private:
|
||||
std::string log_dir;
|
||||
std::string selected_machine;
|
||||
std::shared_ptr<ICloudServiceAgent> m_cloud_agent;
|
||||
|
||||
// Callbacks
|
||||
OnMsgArrivedFn on_ssdp_msg_fn;
|
||||
OnPrinterConnectedFn on_printer_connected_fn;
|
||||
GetSubscribeFailureFn on_subscribe_failure_fn;
|
||||
OnMessageFn on_message_fn;
|
||||
OnMessageFn on_user_message_fn;
|
||||
OnLocalConnectedFn on_local_connect_fn;
|
||||
OnMessageFn on_local_message_fn;
|
||||
QueueOnMainFn queue_on_main_fn;
|
||||
OnServerErrFn on_server_err_fn;
|
||||
|
||||
mutable std::mutex state_mutex;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // __ORCA_PRINTER_AGENT_HPP__
|
||||
@@ -849,7 +849,7 @@ void PresetUpdater::priv::sync_plugins(std::string http_url, std::string plugin_
|
||||
BOOST_LOG_TRIVIAL(info) << "non need to sync plugins for there is no plugins currently.";
|
||||
return;
|
||||
}
|
||||
std::string curr_version = NetworkAgent::use_legacy_network ? BAMBU_NETWORK_AGENT_VERSION_LEGACY : BBL::get_latest_network_version();
|
||||
std::string curr_version = NetworkAgent::use_legacy_network ? BAMBU_NETWORK_AGENT_VERSION_LEGACY : get_latest_network_version();
|
||||
std::string using_version = curr_version.substr(0, 9) + "00";
|
||||
|
||||
std::string cached_version;
|
||||
|
||||
1566
src/slic3r/Utils/QidiPrinterAgent.cpp
Normal file
1566
src/slic3r/Utils/QidiPrinterAgent.cpp
Normal file
File diff suppressed because it is too large
Load Diff
137
src/slic3r/Utils/QidiPrinterAgent.hpp
Normal file
137
src/slic3r/Utils/QidiPrinterAgent.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#ifndef __QIDI_PRINTER_AGENT_HPP__
|
||||
#define __QIDI_PRINTER_AGENT_HPP__
|
||||
|
||||
#include "OrcaPrinterAgent.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class QidiPrinterAgent final : public OrcaPrinterAgent
|
||||
{
|
||||
public:
|
||||
explicit QidiPrinterAgent(std::string log_dir);
|
||||
~QidiPrinterAgent() override;
|
||||
|
||||
static AgentInfo get_agent_info_static();
|
||||
AgentInfo get_agent_info() override { return get_agent_info_static(); }
|
||||
|
||||
int send_message(std::string dev_id, std::string json_str, int qos, int flag) override;
|
||||
int send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag) override;
|
||||
int connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl) override;
|
||||
int disconnect_printer() override;
|
||||
bool start_discovery(bool start, bool sending) override;
|
||||
int bind_detect(std::string dev_ip, std::string sec_link, detectResult& detect) override;
|
||||
|
||||
int set_on_ssdp_msg_fn(OnMsgArrivedFn fn) override;
|
||||
int set_on_printer_connected_fn(OnPrinterConnectedFn fn) override;
|
||||
int set_on_message_fn(OnMessageFn fn) override;
|
||||
int set_on_local_connect_fn(OnLocalConnectedFn fn) override;
|
||||
int set_on_local_message_fn(OnMessageFn fn) override;
|
||||
int set_queue_on_main_fn(QueueOnMainFn fn) override;
|
||||
|
||||
FilamentSyncMode get_filament_sync_mode() const override { return FilamentSyncMode::pull; }
|
||||
void fetch_filament_info(std::string dev_id) override;
|
||||
|
||||
private:
|
||||
struct PrinthostConfig
|
||||
{
|
||||
std::string host;
|
||||
std::string port;
|
||||
std::string api_key;
|
||||
std::string base_url;
|
||||
std::string model_id;
|
||||
std::string model_name;
|
||||
};
|
||||
|
||||
struct QidiDeviceInfo
|
||||
{
|
||||
std::string dev_id;
|
||||
std::string dev_name;
|
||||
std::string model_id;
|
||||
std::string version;
|
||||
};
|
||||
|
||||
struct QidiSlotInfo
|
||||
{
|
||||
int slot_index = 0;
|
||||
int color_index = 0;
|
||||
int filament_type = 0;
|
||||
int vendor_type = 0;
|
||||
bool filament_exists = false;
|
||||
};
|
||||
|
||||
struct QidiFilamentDict
|
||||
{
|
||||
std::map<int, std::string> colors;
|
||||
std::map<int, std::string> filaments;
|
||||
};
|
||||
|
||||
int handle_request(const std::string& dev_id, const std::string& json_str);
|
||||
int send_version_info(const std::string& dev_id);
|
||||
int send_access_code(const std::string& dev_id);
|
||||
|
||||
bool get_printhost_config(PrinthostConfig& config) const;
|
||||
bool fetch_device_info(const std::string& base_url, const std::string& api_key, QidiDeviceInfo& info, std::string& error) const;
|
||||
bool fetch_server_info(const std::string& base_url, const std::string& api_key, std::string& version, std::string& error) const;
|
||||
bool fetch_object_list(const std::string& base_url, const std::string& api_key, std::set<std::string>& objects, std::string& error) const;
|
||||
|
||||
std::string resolve_host(const std::string& dev_id) const;
|
||||
std::string resolve_api_key(const std::string& dev_id, const std::string& fallback) const;
|
||||
void store_host(const std::string& dev_id, const std::string& host, const std::string& api_key);
|
||||
|
||||
bool fetch_slot_info(const std::string& base_url,
|
||||
const std::string& api_key,
|
||||
std::vector<QidiSlotInfo>& slots,
|
||||
int& box_count,
|
||||
std::string& error) const;
|
||||
bool fetch_filament_dict(const std::string& base_url, const std::string& api_key, QidiFilamentDict& dict, std::string& error) const;
|
||||
|
||||
static void parse_ini_section(const std::string& content, const std::string& section_name, std::map<int, std::string>& result);
|
||||
static void parse_filament_sections(const std::string& content, std::map<int, std::string>& result);
|
||||
|
||||
static std::string normalize_color(const std::string& color);
|
||||
static std::string map_filament_type_to_setting_id(const std::string& filament_type);
|
||||
|
||||
void announce_printhost_device();
|
||||
void dispatch_local_connect(int state, const std::string& dev_id, const std::string& msg);
|
||||
void dispatch_printer_connected(const std::string& dev_id);
|
||||
void dispatch_message(const std::string& dev_id, const std::string& payload);
|
||||
void start_status_stream(const std::string& dev_id, const std::string& base_url, const std::string& api_key);
|
||||
void stop_status_stream();
|
||||
void run_status_stream(std::string dev_id, std::string base_url, std::string api_key);
|
||||
void handle_ws_message(const std::string& dev_id, const std::string& payload);
|
||||
void update_status_cache(const nlohmann::json& updates);
|
||||
nlohmann::json build_print_payload_locked(const nlohmann::json* ams_override) const;
|
||||
|
||||
mutable std::mutex state_mutex;
|
||||
std::map<std::string, std::string> host_by_device;
|
||||
std::map<std::string, std::string> api_key_by_device;
|
||||
std::string ssdp_announced_host;
|
||||
std::string ssdp_announced_id;
|
||||
OnMsgArrivedFn on_ssdp_msg_fn;
|
||||
OnPrinterConnectedFn on_printer_connected_fn;
|
||||
OnLocalConnectedFn on_local_connect_fn;
|
||||
OnMessageFn on_message_fn;
|
||||
OnMessageFn on_local_message_fn;
|
||||
QueueOnMainFn queue_on_main_fn;
|
||||
|
||||
mutable std::mutex payload_mutex;
|
||||
nlohmann::json status_cache;
|
||||
nlohmann::json last_ams_payload;
|
||||
|
||||
std::atomic<bool> ws_stop{false};
|
||||
std::atomic<uint64_t> ws_last_emit_ms{0};
|
||||
std::thread ws_thread;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
@@ -10,7 +10,7 @@
|
||||
extern std::string g_log_folder;
|
||||
extern std::string g_log_start_time;
|
||||
|
||||
namespace BBL {
|
||||
namespace Slic3r {
|
||||
|
||||
#define BAMBU_NETWORK_SUCCESS 0
|
||||
#define BAMBU_NETWORK_ERR_INVALID_HANDLE -1
|
||||
|
||||
Reference in New Issue
Block a user