Files
OrcaSlicer/src/slic3r/Utils/bambu_networking.hpp
SoftFever f60e0e776e Add back 02.03.00 plugin to support debugging (#14966)
* Add back 02.03.00 plugin to support debugging
2026-07-26 23:49:53 +08:00

564 lines
23 KiB
C++

#ifndef __BAMBU_NETWORKING_HPP__
#define __BAMBU_NETWORKING_HPP__
#include <string>
#include <functional>
#include <map>
#include <vector>
#include "libslic3r/AppConfig.hpp"
extern std::string g_log_folder;
extern std::string g_log_start_time;
namespace Slic3r {
#define BAMBU_NETWORK_SUCCESS 0
#define BAMBU_NETWORK_ERR_INVALID_HANDLE -1
#define BAMBU_NETWORK_ERR_CONNECT_FAILED -2
#define BAMBU_NETWORK_ERR_DISCONNECT_FAILED -3
#define BAMBU_NETWORK_ERR_SEND_MSG_FAILED -4
#define BAMBU_NETWORK_ERR_BIND_FAILED -5
#define BAMBU_NETWORK_ERR_UNBIND_FAILED -6
#define BAMBU_NETWORK_ERR_REQUEST_SETTING_FAILED -7
#define BAMBU_NETWORK_ERR_PUT_SETTING_FAILED -8
#define BAMBU_NETWORK_ERR_GET_SETTING_LIST_FAILED -9
#define BAMBU_NETWORK_ERR_DEL_SETTING_FAILED -10
#define BAMBU_NETWORK_ERR_GET_USER_PRINTINFO_FAILED -11
#define BAMBU_NETWORK_ERR_QUERY_BIND_INFO_FAILED -12
#define BAMBU_NETWORK_ERR_MODIFY_PRINTER_NAME_FAILED -13
#define BAMBU_NETWORK_ERR_FILE_NOT_EXIST -14
#define BAMBU_NETWORK_ERR_FILE_OVER_SIZE -15
#define BAMBU_NETWORK_ERR_CHECK_MD5_FAILED -16
#define BAMBU_NETWORK_ERR_TIMEOUT -17
#define BAMBU_NETWORK_ERR_CANCELED -18
#define BAMBU_NETWORK_ERR_INVALID_RESULT -19
#define BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED -20
#define BAMBU_NETWORK_ERR_GET_RATING_ID_FAILED -21
#define BAMBU_NETWORK_ERR_OPEN_FILE_FAILED -22
#define BAMBU_NETWORK_ERR_PARSE_CONFIG_FAILED -23
#define BAMBU_NETWORK_ERR_NO_CORRESPONDING_BUCKET -24
#define BAMBU_NETWORK_ERR_GET_INSTANCE_ID_FAILED -25
#define BAMBU_NETWORK_SIGNED_ERROR -26
//bind error
#define BAMBU_NETWORK_ERR_BIND_CREATE_SOCKET_FAILED -1010 //failed to create socket
#define BAMBU_NETWORK_ERR_BIND_SOCKET_CONNECT_FAILED -1020 //failed to socket connect
#define BAMBU_NETWORK_ERR_BIND_PUBLISH_LOGIN_REQUEST -1030 //failed to publish login request
#define BAMBU_NETWORK_ERR_BIND_GET_PRINTER_TICKET_TIMEOUT -1040 //timeout to get ticket from printer
#define BAMBU_NETWORK_ERR_BIND_GET_CLOUD_TICKET_TIMEOUT -1050 //timeout to get ticket from cloud server
#define BAMBU_NETWORK_ERR_BIND_POST_TICKET_TO_CLOUD_FAILED -1060 //failed to post ticket to cloud server
#define BAMBU_NETWORK_ERR_BIND_PARSE_LOGIN_REPORT_FAILED -1070 //failed to parse login report reason no error code
#define BAMBU_NETWORK_ERR_BIND_ECODE_LOGIN_REPORT_FAILED -1080 //failed to parse login report reason has error code
#define BAMBU_NETWORK_ERR_BIND_RECEIVE_LOGIN_REPORT_TIMEOUT -1090 //timeout to receive login report
//start_local_print_with_record error
#define BAMBU_NETWORK_ERR_PRINT_WR_REQUEST_PROJECT_ID_FAILED -2010 //failed to request project id
#define BAMBU_NETWORK_ERR_PRINT_WR_CHECK_MD5_FAILED -2020 //failed to check md5 for upload 3mf to oss
#define BAMBU_NETWORK_ERR_PRINT_WR_UPLOAD_3MF_CONFIG_TO_OSS_FAILED -2030 //failed to upload 3mf config to oss
#define BAMBU_NETWORK_ERR_PRINT_WR_FILE_OVER_SIZE -2040 //the size of the uploaded file cannot exceed 1 GB
#define BAMBU_NETWORK_ERR_PRINT_WR_PUT_NOTIFICATION_FAILED -2050 //timeout to get notification
#define BAMBU_NETWORK_ERR_PRINT_WR_GET_NOTIFICATION_TIMEOUT -2060 //timeout to get notification
#define BAMBU_NETWORK_ERR_PRINT_WR_GET_NOTIFICATION_FAILED -2070 //failed to get notification
#define BAMBU_NETWORK_ERR_PRINT_WR_PATCH_PROJECT_FAILED -2080 //failed to patch project
#define BAMBU_NETWORK_ERR_PRINT_WR_GET_MY_SETTING_FAILED -2090 //failed to get my setting
#define BAMBU_NETWORK_ERR_PRINT_WR_FILE_NOT_EXIST -2100 //3mf file is not exists
#define BAMBU_NETWORK_ERR_PRINT_WR_UPLOAD_3MF_TO_OSS_FAILED -2110 //failed to upload 3mf to oss
#define BAMBU_NETWORK_ERR_PRINT_WR_POST_TASK_FAILED -2120 //failed to post task
#define BAMBU_NETWORK_ERR_PRINT_WR_UPLOAD_FTP_FAILED -2130 //failed to upload to ftp
#define BAMBU_NETWORK_ERR_PRINT_WR_GET_USER_UPLOAD_FAILED -2140 //failed to get_user_upload
//start_print error
#define BAMBU_NETWORK_ERR_PRINT_SP_REQUEST_PROJECT_ID_FAILED -3010 //failed to request project id
#define BAMBU_NETWORK_ERR_PRINT_SP_CHECK_MD5_FAILED -3020 //failed to check md5 for upload 3mf to oss
#define BAMBU_NETWORK_ERR_PRINT_SP_UPLOAD_3MF_CONFIG_TO_OSS_FAILED -3030 //failed to upload 3mf config to oss
#define BAMBU_NETWORK_ERR_PRINT_SP_PUT_NOTIFICATION_FAILED -3040 //failed to put notification
#define BAMBU_NETWORK_ERR_PRINT_SP_GET_NOTIFICATION_TIMEOUT -3050 //timeout to get notification
#define BAMBU_NETWORK_ERR_PRINT_SP_GET_NOTIFICATION_FAILED -3060 //failed to get notification
#define BAMBU_NETWORK_ERR_PRINT_SP_FILE_NOT_EXIST -3070 //3mf file is not exists
#define BAMBU_NETWORK_ERR_PRINT_SP_GET_USER_UPLOAD_FAILED -3080 //failed to get_user_upload
#define BAMBU_NETWORK_ERR_PRINT_SP_FILE_OVER_SIZE -3090 //the size of the uploaded file cannot exceed 1 GB
#define BAMBU_NETWORK_ERR_PRINT_SP_UPLOAD_3MF_TO_OSS_FAILED -3100 //failed to upload 3mf to oss
#define BAMBU_NETWORK_ERR_PRINT_SP_PATCH_PROJECT_FAILED -3110 //failed to patch project
#define BAMBU_NETWORK_ERR_PRINT_SP_POST_TASK_FAILED -3120 //failed to post task
#define BAMBU_NETWORK_ERR_PRINT_SP_WAIT_PRINTER_FAILED -3130 //failed to wait the ack from printer
#define BAMBU_NETOWRK_ERR_PRINT_SP_ENC_FLAG_NOT_READY -3140 //failed to get flag info
//start_local_print error
#define BAMBU_NETWORK_ERR_PRINT_LP_FILE_OVER_SIZE -4010 //the size of the uploaded file cannot exceed 1 GB
#define BAMBU_NETWORK_ERR_PRINT_LP_UPLOAD_FTP_FAILED -4020 //failed to upload ftp
#define BAMBU_NETWORK_ERR_PRINT_LP_PUBLISH_MSG_FAILED -4030 //failed to send mqtt message to device
//start_send_gcode_to_sdcard error
#define BAMBU_NETWORK_ERR_PRINT_SG_UPLOAD_FTP_FAILED -5010 //failed to upload ftp
//connection to printer failed
#define BAMBU_NETWORK_ERR_CONNECTION_TO_PRINTER_FAILED -6010 //Connection to printer failed
#define BAMBU_NETWORK_ERR_CONNECTION_TO_SERVER_FAILED -6020 //Connection to server failed
#define BAMBU_NETWORK_LIBRARY "bambu_networking"
#define BAMBU_NETWORK_AGENT_NAME "bambu_network_agent"
//iot preset type strings
#define IOT_PRINTER_TYPE_STRING "printer"
#define IOT_FILAMENT_STRING "filament"
#define IOT_PRINT_TYPE_STRING "print"
#define IOT_JSON_KEY_VERSION "version"
#define IOT_JSON_KEY_NAME "name"
#define IOT_JSON_KEY_TYPE "type"
#define IOT_JSON_KEY_UPDATE_TIME "update_time"
#define IOT_JSON_KEY_UPDATED_TIME "updated_time"
#define IOT_JSON_KEY_BASE_ID "base_id"
#define IOT_JSON_KEY_SETTING_ID "setting_id"
#define IOT_JSON_KEY_FILAMENT_ID "filament_id"
#define IOT_JSON_KEY_USER_ID "user_id"
// printer callbacks
typedef std::function<void(std::string topic_str)> OnPrinterConnectedFn;
typedef std::function<void(int status, std::string dev_id, std::string msg)> OnLocalConnectedFn;
typedef std::function<void(int return_code, int reason_code)> OnServerConnectedFn;
typedef std::function<void(std::string dev_id, std::string msg)> OnMessageFn;
// http callbacks
typedef std::function<void(unsigned http_code, std::string http_body)> OnHttpErrorFn;
typedef std::function<std::string()> GetCountryCodeFn;
typedef std::function<void(std::string topic)> GetSubscribeFailureFn;
// print callbacks
typedef std::function<void(int status, int code, std::string msg)> OnUpdateStatusFn;
typedef std::function<bool()> WasCancelledFn;
typedef std::function<bool(int status, std::string job_info)> OnWaitFn;
typedef std::function<void(int online_login, bool login)> OnUserLoginFn;
// local callbacks
typedef std::function<void(std::string dev_info_json_str)> OnMsgArrivedFn;
// queue call to main thread
typedef std::function<void(std::function<void()>)> QueueOnMainFn;
typedef std::function<void(int progress)> ProgressFn;
typedef std::function<void(int retcode, std::string info)> LoginFn;
typedef std::function<void(int result, std::string info)> ResultFn;
typedef std::function<bool()> CancelFn;
typedef std::function<bool(std::map<std::string, std::string> info)> CheckFn;
//err callbacks
typedef std::function<void(std::string url, int status)> OnServerErrFn;
enum SendingPrintJobStage {
PrintingStageCreate = 0,
PrintingStageUpload = 1,
PrintingStageWaiting = 2,
PrintingStageSending = 3,
PrintingStageRecord = 4,
PrintingStageWaitPrinter = 5,
PrintingStageFinished = 6,
PrintingStageERROR = 7,
PrintingStageLimit = 8,
};
enum PublishingStage {
PublishingCreate = 0,
PublishingUpload = 1,
PublishingWaiting = 2,
PublishingJumpUrl = 3,
};
enum BindJobStage {
LoginStageConnect = 0,
LoginStageLogin = 1,
LoginStageWaitForLogin = 2,
LoginStageGetIdentify = 3,
LoginStageWaitAuth = 4,
LoginStageFinished = 5,
};
enum ConnectStatus {
ConnectStatusOk = 0,
ConnectStatusFailed = 1,
ConnectStatusLost = 2,
};
struct detectResult {
std::string result_msg;
std::string command;
std::string dev_id;
std::string model_id;
std::string dev_name;
std::string version;
std::string bind_state;
std::string connect_type;
};
/* print job*/
struct PrintParams_Legacy {
/* basic info */
std::string dev_id;
std::string task_name;
std::string project_name;
std::string preset_name;
std::string filename;
std::string config_filename;
int plate_index;
std::string ftp_folder;
std::string ftp_file;
std::string ftp_file_md5;
std::string ams_mapping;
std::string ams_mapping_info;
std::string connection_type;
std::string comments;
int origin_profile_id = 0;
int stl_design_id = 0;
std::string origin_model_id;
std::string print_type;
std::string dst_file;
std::string dev_name;
/* access options */
std::string dev_ip;
bool use_ssl_for_ftp;
bool use_ssl_for_mqtt;
std::string username;
std::string password;
/*user options */
bool task_bed_leveling; /* bed leveling of task */
bool task_flow_cali; /* flow calibration of task */
bool task_vibration_cali; /* vibration calibration of task */
bool task_layer_inspect; /* first layer inspection of task */
bool task_record_timelapse; /* record timelapse of task */
bool task_use_ams;
std::string task_bed_type;
std::string extra_options;
};
/* print job, as the 02.03.00 series expects it. The 02.08.01 series inserted
task_timelapse_use_internal, extruder_cali_manual_mode, svc_context and slicer_uid into
PrintParams; two of them sit mid-struct, so an older plug-in misreads every field from
task_use_ams onwards if handed the current layout. Rebuild it with as_0203() instead. */
struct PrintParams_0203 {
/* basic info */
std::string dev_id;
std::string task_name;
std::string project_name;
std::string preset_name;
std::string filename;
std::string config_filename;
int plate_index;
std::string ftp_folder;
std::string ftp_file;
std::string ftp_file_md5;
std::string nozzle_mapping;
std::string ams_mapping;
std::string ams_mapping2;
std::string ams_mapping_info;
std::string nozzles_info;
std::string connection_type;
std::string comments;
int origin_profile_id = 0;
int stl_design_id = 0;
std::string origin_model_id;
std::string print_type;
std::string dst_file;
std::string dev_name;
/* access options */
std::string dev_ip;
bool use_ssl_for_ftp;
bool use_ssl_for_mqtt;
std::string username;
std::string password;
/*user options */
bool task_bed_leveling; /* bed leveling of task */
bool task_flow_cali; /* flow calibration of task */
bool task_vibration_cali; /* vibration calibration of task */
bool task_layer_inspect; /* first layer inspection of task */
bool task_record_timelapse; /* record timelapse of task */
bool task_use_ams;
std::string task_bed_type;
std::string extra_options;
int auto_bed_leveling{ 0 };
int auto_flow_cali{ 0 };
int auto_offset_cali{ 0 };
bool task_ext_change_assist;
bool try_emmc_print;
};
/* print job*/
struct PrintParams {
/* basic info */
std::string dev_id;
std::string task_name;
std::string project_name;
std::string preset_name;
std::string filename;
std::string config_filename;
int plate_index;
std::string ftp_folder;
std::string ftp_file;
std::string ftp_file_md5;
std::string nozzle_mapping;
std::string ams_mapping;
std::string ams_mapping2;
std::string ams_mapping_info;
std::string nozzles_info;
std::string connection_type;
std::string comments;
int origin_profile_id = 0;
int stl_design_id = 0;
std::string origin_model_id;
std::string print_type;
std::string dst_file;
std::string dev_name;
/* access options */
std::string dev_ip;
bool use_ssl_for_ftp;
bool use_ssl_for_mqtt;
std::string username;
std::string password;
/*user options */
bool task_bed_leveling; /* bed leveling of task */
bool task_flow_cali; /* flow calibration of task */
bool task_vibration_cali; /* vibration calibration of task */
bool task_layer_inspect; /* first layer inspection of task */
bool task_record_timelapse; /* record timelapse of task */
bool task_timelapse_use_internal;
bool task_use_ams;
std::string task_bed_type;
std::string extra_options;
int auto_bed_leveling{ 0 };
int auto_flow_cali{ 0 };
int auto_offset_cali{ 0 };
int extruder_cali_manual_mode{ -1 };
bool task_ext_change_assist;
bool try_emmc_print;
std::string svc_context;
std::string slicer_uid;
};
struct TaskQueryParams
{
std::string dev_id;
int status = 0;
int offset = 0;
int limit = 20;
};
struct FilamentQueryParams
{
std::string category;
std::string status;
std::string spool_id;
std::string rfid;
int offset = 0;
int limit = 20;
};
struct FilamentDeleteParams
{
std::vector<std::string> ids;
std::vector<std::string> rfids;
};
struct AmsSyncItem {
std::string RFID;
std::string filamentVendor;
std::string filamentType;
std::string filamentName;
std::string filamentId;
bool isSupport = false;
std::string color;
int colorType = 0;
std::vector<std::string> colors;
int netWeight = 0;
int totalNetWeight = 0;
std::string trayIdName;
std::string note;
std::string amsSn;
std::string slotId;
int amsId = 0;
int amsType = 0;
bool createNew = false;
};
struct AmsSyncParams {
std::string devId;
std::vector<AmsSyncItem> items;
};
struct PublishParams {
std::string project_name;
std::string project_3mf_file;
std::string preset_name;
std::string project_model_id;
std::string design_id;
std::string config_filename;
};
struct CertificateInformation {
std::string issuer;
std::string sub_name;
std::string start_date;
std::string end_date;
std::string serial_number;
};
// The plug-in ABI generation a library speaks. Generations differ in by-value struct layouts and
// function signatures, so a call must go through the matching typedefs (see BBLPrinterAgent) -
// the wrong one corrupts the stack rather than failing cleanly.
enum class NetworkAbi {
Unsupported, // no generation in this build can call it - never dispatch through it
Legacy, // 01.10.01: PrintParams_Legacy; send_message/send_message_to_printer take no flag
V0203, // 02.03.00: PrintParams_0203; bind takes no dev_model
Current, // 02.08.01: the layouts and signatures this build declares directly
};
struct NetworkLibraryVersion {
const char* version;
const char* display_name;
const char* url_override;
bool is_latest;
const char* warning;
NetworkAbi abi;
};
// Every row names the generation that can call it, so a series can never be offered without a
// host-side ABI for it. Series with no generation - 02.01.01, 02.00.02 and older - must stay out;
// is_supported_network_version() is the gate that keeps them from loading.
static const NetworkLibraryVersion AVAILABLE_NETWORK_VERSIONS[] = {
{"02.08.01", "02.08.01", nullptr, true, nullptr, NetworkAbi::Current},
{"02.03.00", "02.03.00", nullptr, false,
"An older plug-in series. Features that need newer plug-in support, such as print-failure "
"snapshots in the device error dialog, are unavailable.", NetworkAbi::V0203},
{BAMBU_NETWORK_AGENT_VERSION_LEGACY, BAMBU_NETWORK_AGENT_VERSION_LEGACY " (legacy)", nullptr, false, nullptr, NetworkAbi::Legacy},
};
static const size_t AVAILABLE_NETWORK_VERSIONS_COUNT = sizeof(AVAILABLE_NETWORK_VERSIONS) / sizeof(AVAILABLE_NETWORK_VERSIONS[0]);
inline const char* get_latest_network_version() {
for (size_t i = 0; i < AVAILABLE_NETWORK_VERSIONS_COUNT; ++i) {
if (AVAILABLE_NETWORK_VERSIONS[i].is_latest)
return AVAILABLE_NETWORK_VERSIONS[i].version;
}
return AVAILABLE_NETWORK_VERSIONS[0].version;
}
// The AA.BB.CC series of a modern version string - the plug-in's stored identity. The 4th
// component is only which build of the series happens to be installed and is read live from
// the loaded plug-in for display. Legacy keeps its exact string (the shim matches exactly).
inline std::string network_plugin_series(const std::string& version) {
if (version.empty() || version == BAMBU_NETWORK_AGENT_VERSION_LEGACY)
return version;
return version.size() >= 8 ? version.substr(0, 8) : version;
}
// Index of the whitelist entry that can load this version: an exact match, or a build of the same
// AA.BB.CC series as a non-legacy entry (the ABI is stable within a series, and the OTA sync only
// installs same-series updates). Legacy matches exactly only - a sibling build of that series
// would come through the modern layout. AVAILABLE_NETWORK_VERSIONS_COUNT when nothing matches.
inline size_t find_network_version_index(const std::string& version) {
const std::string series = network_plugin_series(version);
for (size_t i = 0; i < AVAILABLE_NETWORK_VERSIONS_COUNT; ++i) {
const std::string base = AVAILABLE_NETWORK_VERSIONS[i].version;
if (version == base)
return i;
if (base == BAMBU_NETWORK_AGENT_VERSION_LEGACY)
continue;
if (series == base)
return i;
}
return AVAILABLE_NETWORK_VERSIONS_COUNT;
}
// True when a whitelisted series can load the version through an ABI this build implements.
inline bool is_supported_network_version(const std::string& version) {
return find_network_version_index(version) < AVAILABLE_NETWORK_VERSIONS_COUNT;
}
// The generation to call a loaded library through. Unsupported for anything the load gate rejects,
// so a mislabelled library reaches no plug-in call instead of a layout it does not share.
inline NetworkAbi network_plugin_abi(const std::string& version) {
const size_t i = find_network_version_index(version);
return i < AVAILABLE_NETWORK_VERSIONS_COUNT ? AVAILABLE_NETWORK_VERSIONS[i].abi : NetworkAbi::Unsupported;
}
struct NetworkLibraryVersionInfo {
std::string version;
std::string base_version;
std::string suffix;
std::string display_name;
std::string url_override;
bool is_latest;
std::string warning;
bool is_discovered;
// Whether this is the build currently loaded in this session. Deliberately not
// "present on disk": switching versions leaves the previous library in place, so
// an on-disk test marks every version ever selected.
bool is_loaded = false;
static NetworkLibraryVersionInfo from_static(const NetworkLibraryVersion& v) {
return {
v.version,
v.version,
"",
v.display_name,
v.url_override ? v.url_override : "",
false, // assigned by get_all_available_versions() once the list is sorted
v.warning ? v.warning : "",
false
};
}
static NetworkLibraryVersionInfo from_discovered(const std::string& full_version,
const std::string& base,
const std::string& sfx) {
return {full_version, base, sfx, full_version, "", false, "", true};
}
};
inline std::string extract_base_version(const std::string& full_version) {
auto pos = full_version.find('-');
return (pos == std::string::npos) ? full_version : full_version.substr(0, pos);
}
inline std::string extract_suffix(const std::string& full_version) {
auto pos = full_version.find('-');
return (pos == std::string::npos) ? "" : full_version.substr(pos + 1);
}
// True when the version is a pure dotted-numeric build (AA.BB.CC or AA.BB.CC.DD) whose identity
// collapses to its series - the managed/OTA build. Legacy and any custom-named build
// (02.08.01_custom, 02.08.01.52-dev) are NOT managed: they are genuinely distinct files kept
// under their own name and never folded into the series entry.
inline bool is_series_managed_version(const std::string& version) {
if (version.empty() || version == BAMBU_NETWORK_AGENT_VERSION_LEGACY)
return false;
return version.find_first_not_of("0123456789.") == std::string::npos;
}
// Selectable versions, newest first. Marks the entry matching the plug-in currently
// loaded in this session.
std::vector<NetworkLibraryVersionInfo> get_all_available_versions();
// Same list, resolving is_loaded against an explicitly supplied version rather than the
// live plug-in. Pass an empty string for "nothing loaded".
std::vector<NetworkLibraryVersionInfo> get_all_available_versions(const std::string& loaded_version);
struct NetworkLibraryLoadError {
bool has_error = false;
std::string message;
std::string technical_details;
std::string attempted_path;
};
enum class MessageFlag : int
{
MSG_FLAG_NONE = 0,
MSG_SIGN = 1 << 0,
MSG_ENCRYPT = 1 << 1,
};
}
#endif