mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-14 12:05:06 +03:00
Compare commits
4 Commits
refactor/p
...
color-mixi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f66c536ca | ||
|
|
d322b1a156 | ||
|
|
ee6613a4b8 | ||
|
|
e9d421050e |
@@ -5378,7 +5378,7 @@ void PresetBundle::update_multi_material_filament_presets(size_t to_delete_filam
|
||||
f_multiplier.resize(nozzle_nums, 1.f);
|
||||
}
|
||||
|
||||
if ( (num_filaments * num_filaments) != size_t(old_matrix.size() / old_nozzle_nums) ) {
|
||||
if (old_matrix.size() != num_filaments * num_filaments * nozzle_nums) {
|
||||
// First verify if purging volumes presets for each extruder matches number of extruders
|
||||
std::vector<double>& filaments = this->project_config.option<ConfigOptionFloats>("flush_volumes_vector")->values;
|
||||
while (filaments.size() < 2* num_filaments) {
|
||||
|
||||
@@ -559,9 +559,11 @@ static inline bool model_volume_solid_or_modifier(const ModelVolume &mv)
|
||||
|
||||
static inline Transform3f trafo_for_bbox(const Transform3d &object_trafo, const Transform3d &volume_trafo)
|
||||
{
|
||||
Transform3d m = object_trafo * volume_trafo;
|
||||
m.translation().x() = 0.;
|
||||
m.translation().y() = 0.;
|
||||
// Orca: Keep the volume's local XY offset for multipart overlap checks, but remove the object's bed placement.
|
||||
Transform3d object_trafo_local = object_trafo;
|
||||
object_trafo_local.translation().x() = 0.;
|
||||
object_trafo_local.translation().y() = 0.;
|
||||
Transform3d m = object_trafo_local * volume_trafo;
|
||||
return m.cast<float>();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
|
||||
#include "libslic3r/Time.hpp"
|
||||
|
||||
#include "IPrinterAgent.hpp"
|
||||
|
||||
using namespace nlohmann;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
#include "DeviceCore/DevStatus.h"
|
||||
#include "DeviceCore/DevUpgrade.h"
|
||||
|
||||
#include "IPrinterAgent.hpp"
|
||||
|
||||
#define CALI_DEBUG
|
||||
#define MINUTE_30 1800000 //ms
|
||||
@@ -1439,29 +1438,26 @@ int MachineObject::command_upgrade_module(std::string url, std::string module_ty
|
||||
|
||||
int MachineObject::command_xyz_abs()
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
int rtn = m_agent->command_xyz_abs(get_dev_id(), MachineObject::m_sequence_id++, is_lan_mode_printer());
|
||||
if (rtn == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED || rtn == ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE)
|
||||
show_unsupported_dlg(rtn);
|
||||
return rtn;
|
||||
return this->publish_gcode("G90 \n");
|
||||
}
|
||||
|
||||
int MachineObject::command_auto_leveling()
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
int rtn = m_agent->command_auto_leveling(get_dev_id(), MachineObject::m_sequence_id++, is_lan_mode_printer());
|
||||
if (rtn == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED || rtn == ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE)
|
||||
show_unsupported_dlg(rtn);
|
||||
return rtn;
|
||||
return this->publish_gcode("G29 \n");
|
||||
}
|
||||
|
||||
int MachineObject::command_go_home()
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
int rtn = m_agent->command_go_home(get_dev_id(), this->is_in_printing(), m_support_mqtt_homing, MachineObject::m_sequence_id++, is_lan_mode_printer());
|
||||
if (rtn == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED || rtn == ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE)
|
||||
show_unsupported_dlg(rtn);
|
||||
return rtn;
|
||||
if (m_support_mqtt_homing)
|
||||
{
|
||||
json j;
|
||||
j["print"]["command"] = "back_to_center";
|
||||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
||||
return this->publish_json(j);
|
||||
}
|
||||
|
||||
// gcode command
|
||||
return this->is_in_printing() ? this->publish_gcode("G28 X\n") : this->publish_gcode("G28 \n");
|
||||
}
|
||||
|
||||
int MachineObject::command_task_partskip(std::vector<int> part_ids)
|
||||
@@ -1583,20 +1579,23 @@ int MachineObject::command_stop_buzzer()
|
||||
|
||||
int MachineObject::command_set_bed(int temp)
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
int rtn = m_agent->command_set_bed(get_dev_id(), temp, m_support_mqtt_bet_ctrl, MachineObject::m_sequence_id++, is_lan_mode_printer());
|
||||
if (rtn == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED || rtn == ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE)
|
||||
show_unsupported_dlg(rtn);
|
||||
return rtn;
|
||||
if (m_support_mqtt_bet_ctrl)
|
||||
{
|
||||
json j;
|
||||
j["print"]["command"] = "set_bed_temp";
|
||||
j["print"]["temp"] = temp;
|
||||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
||||
return this->publish_json(j);
|
||||
}
|
||||
|
||||
std::string gcode_str = (boost::format("M140 S%1%\n") % temp).str();
|
||||
return this->publish_gcode(gcode_str);
|
||||
}
|
||||
|
||||
int MachineObject::command_set_nozzle(int temp)
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
int rtn = m_agent->command_set_nozzle(get_dev_id(), temp, MachineObject::m_sequence_id++, is_lan_mode_printer());
|
||||
if (rtn == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED || rtn == ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE)
|
||||
show_unsupported_dlg(rtn);
|
||||
return rtn;
|
||||
std::string gcode_str = (boost::format("M104 S%1%\n") % temp).str();
|
||||
return this->publish_gcode(gcode_str);
|
||||
}
|
||||
|
||||
int MachineObject::command_set_nozzle_new(int nozzle_id, int temp)
|
||||
@@ -1701,11 +1700,9 @@ int MachineObject::command_ams_user_settings(bool start_read_opt, bool tray_read
|
||||
|
||||
int MachineObject::command_ams_calibrate(int ams_id)
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
int rtn = m_agent->command_ams_calibrate(get_dev_id(), ams_id, MachineObject::m_sequence_id++, is_lan_mode_printer());
|
||||
if (rtn == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED || rtn == ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE)
|
||||
show_unsupported_dlg(rtn);
|
||||
return rtn;
|
||||
std::string gcode_cmd = (boost::format("M620 C%1% \n") % ams_id).str();
|
||||
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode_cmd;
|
||||
return this->publish_gcode(gcode_cmd);
|
||||
}
|
||||
|
||||
int MachineObject::command_ams_filament_settings(int ams_id, int slot_id, std::string filament_id, std::string setting_id, std::string tray_color, std::string tray_type, int nozzle_temp_min, int nozzle_temp_max)
|
||||
@@ -1743,11 +1740,9 @@ int MachineObject::command_ams_filament_settings(int ams_id, int slot_id, std::s
|
||||
|
||||
int MachineObject::command_ams_refresh_rfid(std::string tray_id)
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
int rtn = m_agent->command_ams_refresh_rfid(get_dev_id(), tray_id, MachineObject::m_sequence_id++, is_lan_mode_printer());
|
||||
if (rtn == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED || rtn == ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE)
|
||||
show_unsupported_dlg(rtn);
|
||||
return rtn;
|
||||
std::string gcode_cmd = (boost::format("M620 R%1% \n") % tray_id).str();
|
||||
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode_cmd;
|
||||
return this->publish_gcode(gcode_cmd);
|
||||
}
|
||||
|
||||
int MachineObject::command_ams_refresh_rfid2(int ams_id, int slot_id)
|
||||
@@ -1763,11 +1758,9 @@ int MachineObject::command_ams_refresh_rfid2(int ams_id, int slot_id)
|
||||
|
||||
int MachineObject::command_ams_select_tray(std::string tray_id)
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
int rtn = m_agent->command_ams_select_tray(get_dev_id(), tray_id, MachineObject::m_sequence_id++, is_lan_mode_printer());
|
||||
if (rtn == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED || rtn == ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE)
|
||||
show_unsupported_dlg(rtn);
|
||||
return rtn;
|
||||
std::string gcode_cmd = (boost::format("M620 P%1% \n") % tray_id).str();
|
||||
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode_cmd;
|
||||
return this->publish_gcode(gcode_cmd);
|
||||
}
|
||||
|
||||
int MachineObject::command_ams_control(std::string action)
|
||||
@@ -1926,12 +1919,47 @@ int MachineObject::command_ams_air_print_detect(bool air_print_detect)
|
||||
|
||||
int MachineObject::command_axis_control(std::string axis, double unit, double input_val, int speed)
|
||||
{
|
||||
if (!m_agent) return -1;
|
||||
int rtn = m_agent->command_axis_control(get_dev_id(), axis, unit, input_val, speed, is_core_xy(),
|
||||
m_support_mqtt_axis_control, MachineObject::m_sequence_id++, is_lan_mode_printer());
|
||||
if (rtn == ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED || rtn == ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE)
|
||||
show_unsupported_dlg(rtn);
|
||||
return rtn;
|
||||
if (m_support_mqtt_axis_control)
|
||||
{
|
||||
int dir = input_val > 0 ? 1 : -1;
|
||||
// i3-arch printers move the bed for Y/Z, so the on-screen direction is
|
||||
// reversed — same negation the g-code fallback below applies.
|
||||
if (!is_core_xy() && (axis.compare("Y") == 0 || axis.compare("Z") == 0)) {
|
||||
dir = -dir;
|
||||
}
|
||||
|
||||
json j;
|
||||
j["print"]["command"] = "xyz_ctrl";
|
||||
j["print"]["axis"] = axis;
|
||||
j["print"]["dir"] = dir;
|
||||
j["print"]["mode"] = (std::abs(input_val) >= 10) ? 1 : 0;
|
||||
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
|
||||
return this->publish_json(j);
|
||||
}
|
||||
|
||||
double value = input_val;
|
||||
if (!is_core_xy()) {
|
||||
if ( axis.compare("Y") == 0
|
||||
|| axis.compare("Z") == 0) {
|
||||
value = -1.0 * input_val;
|
||||
}
|
||||
}
|
||||
|
||||
char cmd[256];
|
||||
if (axis.compare("X") == 0
|
||||
|| axis.compare("Y") == 0
|
||||
|| axis.compare("Z") == 0) {
|
||||
sprintf(cmd, "M211 S \nM211 X1 Y1 Z1\nM1002 push_ref_mode\nG91 \nG1 %s%0.1f F%d\nM1002 pop_ref_mode\nM211 R\n", axis.c_str(), value * unit, speed);
|
||||
}
|
||||
else if (axis.compare("E") == 0) {
|
||||
sprintf(cmd, "M83 \nG0 %s%0.1f F%d\n", axis.c_str(), value * unit, speed);
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return this->publish_gcode(cmd);
|
||||
}
|
||||
|
||||
int MachineObject::command_extruder_control(int nozzle_id, double val)
|
||||
@@ -2569,7 +2597,7 @@ void MachineObject::set_print_state(std::string status)
|
||||
int MachineObject::connect(bool use_openssl)
|
||||
{
|
||||
if (get_dev_ip().empty()) return -1;
|
||||
std::string username = m_agent ? m_agent->default_lan_username() : std::string();
|
||||
std::string username = "bblp";
|
||||
std::string password = get_access_code();
|
||||
|
||||
if (m_agent) {
|
||||
|
||||
@@ -100,32 +100,6 @@ struct DevPrintTaskRatingInfo;
|
||||
// given nozzle diameter (mm), bucketed per nozzle size to mirror the printer firmware.
|
||||
bool is_stringing_prone_filament(const std::string& filament_id, float nozzle_diameter);
|
||||
|
||||
enum LiveviewLocal {
|
||||
LVL_None,
|
||||
LVL_Disable,
|
||||
LVL_Local,
|
||||
LVL_Rtsps,
|
||||
LVL_Rtsp
|
||||
};
|
||||
|
||||
enum LiveviewRemote {
|
||||
LVR_None,
|
||||
LVR_Tutk,
|
||||
LVR_Agora,
|
||||
LVR_TutkAgora
|
||||
};
|
||||
|
||||
enum FileLocal {
|
||||
FL_None,
|
||||
FL_Local
|
||||
};
|
||||
|
||||
enum FileRemote {
|
||||
FR_None,
|
||||
FR_Tutk,
|
||||
FR_Agora,
|
||||
FR_TutkAgora
|
||||
};
|
||||
|
||||
class MachineObject
|
||||
{
|
||||
@@ -564,10 +538,29 @@ public:
|
||||
time_t xcam_first_layer_hold_start = 0;
|
||||
std::string local_rtsp_url;
|
||||
std::string tutk_state;
|
||||
LiveviewLocal liveview_local{ LiveviewLocal::LVL_None };
|
||||
LiveviewRemote liveview_remote{ LiveviewRemote::LVR_None};
|
||||
FileLocal file_local{ FileLocal::FL_None };
|
||||
FileRemote file_remote{ FileRemote::FR_None };
|
||||
enum LiveviewLocal {
|
||||
LVL_None,
|
||||
LVL_Disable,
|
||||
LVL_Local,
|
||||
LVL_Rtsps,
|
||||
LVL_Rtsp
|
||||
} liveview_local{ LVL_None };
|
||||
enum LiveviewRemote {
|
||||
LVR_None,
|
||||
LVR_Tutk,
|
||||
LVR_Agora,
|
||||
LVR_TutkAgora
|
||||
} liveview_remote{ LVR_None };
|
||||
enum FileLocal {
|
||||
FL_None,
|
||||
FL_Local
|
||||
} file_local{ FL_None };
|
||||
enum FileRemote {
|
||||
FR_None,
|
||||
FR_Tutk,
|
||||
FR_Agora,
|
||||
FR_TutkAgora
|
||||
} file_remote{ FR_None };
|
||||
|
||||
enum PlateMakerDectect : int
|
||||
{
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
#include "slic3r/GUI/DeviceCore/DevManager.h"
|
||||
#include "slic3r/GUI/DeviceCore/DevUtil.h"
|
||||
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "slic3r/Utils/FileTransferUtils.hpp"
|
||||
#include "slic3r/Utils/BBLNetworkPlugin.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
@@ -203,9 +204,54 @@ void PrintJob::process(Ctl &ctl)
|
||||
params.dev_ip = m_dev_ip;
|
||||
params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
|
||||
params.use_ssl_for_mqtt = m_local_use_ssl;
|
||||
params.username = m_agent->default_lan_username();
|
||||
params.username = "bblp";
|
||||
params.password = m_access_code;
|
||||
|
||||
// check access code and ip address
|
||||
if (this->connection_type == "lan" && m_print_type == "from_normal") {
|
||||
bool emmc_ok = false;
|
||||
bool ftp_ok = false;
|
||||
if (could_emmc_print) {
|
||||
std::string devIP = m_dev_ip;
|
||||
std::string accessCode = m_access_code;
|
||||
std::string url = "bambu:///local/" + devIP + "?port=6000&user=" + "bblp" + "&passwd=" + accessCode;
|
||||
try {
|
||||
std::unique_ptr<FileTransferTunnel> tunnel = std::make_unique<FileTransferTunnel>(module(), url);
|
||||
emmc_ok = tunnel->sync_start_connect();
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "eMMC tunnel unavailable, falling back to FTP: " << e.what();
|
||||
emmc_ok = false;
|
||||
}
|
||||
}
|
||||
{
|
||||
params.dev_id = m_dev_id;
|
||||
params.project_name = "verify_job";
|
||||
params.filename = job_data._temp_path.string();
|
||||
params.connection_type = this->connection_type;
|
||||
|
||||
result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr, nullptr);
|
||||
|
||||
ftp_ok = result == 0;
|
||||
}
|
||||
if (!emmc_ok && !ftp_ok) {
|
||||
bool legacy_mode = BBLNetworkPlugin::instance().use_legacy_network();
|
||||
BOOST_LOG_TRIVIAL(error) << "LAN connection verification failed:"
|
||||
<< " emmc_ok=" << emmc_ok
|
||||
<< ", ftp_ok=" << ftp_ok
|
||||
<< ", ftp_result=" << result
|
||||
<< ", dev_ip=" << m_dev_ip
|
||||
<< ", dev_id=" << m_dev_id
|
||||
<< ", password_length=" << m_access_code.size()
|
||||
<< ", legacy_mode=" << (legacy_mode ? "true" : "false");
|
||||
m_enter_ip_address_fun_fail();
|
||||
m_job_finished = true;
|
||||
return;
|
||||
}
|
||||
|
||||
params.project_name = "";
|
||||
params.filename = "";
|
||||
}
|
||||
|
||||
params.dev_id = m_dev_id;
|
||||
params.ftp_folder = m_ftp_folder;
|
||||
params.filename = job_data._3mf_path.string();
|
||||
@@ -241,7 +287,7 @@ void PrintJob::process(Ctl &ctl)
|
||||
if (v == "0" || v == "false")
|
||||
disable_emmc = false;
|
||||
}
|
||||
params.try_emmc_print = this->could_emmc_print && !disable_emmc;
|
||||
params.try_emmc_print = this->could_emmc_print && !disable_emmc;
|
||||
|
||||
if (m_print_type == "from_sdcard_view") {
|
||||
params.dst_file = m_dst_path;
|
||||
@@ -596,13 +642,6 @@ void PrintJob::process(Ctl &ctl)
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
if (result == ORCA_NETWORK_ERR_ACCESS_VERIFICATION_FAILED) {
|
||||
if (m_enter_ip_address_fun_fail)
|
||||
m_enter_ip_address_fun_fail();
|
||||
m_job_finished = true;
|
||||
return;
|
||||
}
|
||||
|
||||
curr_percent = -1;
|
||||
|
||||
// The printer is still fetching its encryption flag (a transient state), so ask the
|
||||
|
||||
@@ -124,7 +124,7 @@ void SendJob::process(Ctl &ctl)
|
||||
if (m_is_check_mode) {
|
||||
PrintParams verify_params;
|
||||
verify_params.dev_ip = m_dev_ip;
|
||||
verify_params.username = agent->default_lan_username();
|
||||
verify_params.username = "bblp";
|
||||
verify_params.password = m_access_code;
|
||||
verify_params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
|
||||
verify_params.use_ssl_for_mqtt = m_local_use_ssl;
|
||||
@@ -209,7 +209,7 @@ void SendJob::process(Ctl &ctl)
|
||||
|
||||
// local print access
|
||||
params.dev_ip = m_dev_ip;
|
||||
params.username = agent->default_lan_username();
|
||||
params.username = "bblp";
|
||||
params.password = m_access_code;
|
||||
params.use_ssl_for_ftp = m_local_use_ssl_for_ftp;
|
||||
params.use_ssl_for_mqtt = m_local_use_ssl;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "Widgets/ProgressDialog.hpp"
|
||||
#include <libslic3r/Model.hpp>
|
||||
#include <libslic3r/Format/bbs_3mf.hpp>
|
||||
#include <slic3r/GUI/DeviceManager.hpp>
|
||||
#include "DeviceCore/DevStorage.h"
|
||||
|
||||
#ifdef __WXMSW__
|
||||
@@ -207,6 +206,7 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
|
||||
Bind(wxEVT_SHOW, onShowHide);
|
||||
parent->GetParent()->Bind(wxEVT_SHOW, onShowHide);
|
||||
|
||||
m_lan_user = "bblp";
|
||||
}
|
||||
|
||||
MediaFilePanel::~MediaFilePanel()
|
||||
@@ -465,19 +465,15 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr<PrinterFileSystem> wfs)
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaFilePanel::fetchUrl: " << m_local_proto << m_remote_proto;
|
||||
m_waiting_support = false;
|
||||
NetworkAgent *agent = wxGetApp().getAgent();
|
||||
if (agent && (m_lan_mode || !m_remote_proto) && m_local_proto && !m_lan_ip.empty()) {
|
||||
agent->get_file_transfer_url(
|
||||
m_machine,
|
||||
[this, wfs](FileTransferURLResult result) {
|
||||
CallAfter([this, wfs, result = std::move(result)] {
|
||||
auto fs = wfs.lock();
|
||||
if (!fs || fs != m_image_grid->GetFileSystem())
|
||||
return;
|
||||
fs->SetUrl(result.is_success ? result.url : std::to_string(result.error_code));
|
||||
});
|
||||
},
|
||||
{URL_TCP, m_lan_ip, agent->default_lan_username(), m_lan_passwd,
|
||||
m_machine, agent->get_version(), m_dev_ver, "", wxGetApp().app_config->get("slicer_uuid"), SLIC3R_VERSION});
|
||||
std::string agent_version = agent ? agent->get_version() : "";
|
||||
if ((m_lan_mode || !m_remote_proto) && m_local_proto && !m_lan_ip.empty()) {
|
||||
std::string url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
|
||||
url += "&device=" + m_machine;
|
||||
url += "&net_ver=" + agent_version;
|
||||
url += "&dev_ver=" + m_dev_ver;
|
||||
url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid");
|
||||
url += "&cli_ver=" + std::string(SLIC3R_VERSION);
|
||||
fs->SetUrl(url);
|
||||
return;
|
||||
}
|
||||
if (!m_remote_proto && m_local_proto) { // not support tutk
|
||||
@@ -496,25 +492,35 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr<PrinterFileSystem> wfs)
|
||||
return;
|
||||
}
|
||||
if (agent) {
|
||||
agent->get_file_transfer_url(
|
||||
m_machine,
|
||||
[this, wfs, m = m_machine](FileTransferURLResult result) {
|
||||
std::string url = std::move(result.url);
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaFilePanel::fetchUrl: file_system_url: " << hide_passwd(url, {"?uid=", "authkey=", "passwd="});
|
||||
std::string protocols[] = {"", "\"tutk\"", "\"agora\"", "\"tutk\",\"agora\""};
|
||||
agent->get_camera_url(m_machine + "|" + m_dev_ver + "|" + protocols[m_remote_proto],
|
||||
[this, wfs, m = m_machine, v = agent->get_version(), dv = m_dev_ver](std::string url) {
|
||||
if (boost::algorithm::starts_with(url, "bambu:///")) {
|
||||
url += "&device=" + m;
|
||||
url += "&net_ver=" + v;
|
||||
url += "&dev_ver=" + dv;
|
||||
url += "&refresh_url=" + boost::lexical_cast<std::string>(&refresh_agora_url);
|
||||
url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid");
|
||||
url += "&cli_ver=" + std::string(SLIC3R_VERSION);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaFilePanel::fetchUrl: camera_url: " << hide_passwd(url, {"?uid=", "authkey=", "passwd="});
|
||||
CallAfter([=] {
|
||||
boost::shared_ptr fs(wfs.lock());
|
||||
if (!fs || fs != m_image_grid->GetFileSystem()) return;
|
||||
if (result.is_success) {
|
||||
if (boost::algorithm::starts_with(url, "bambu:///")) {
|
||||
fs->SetUrl(url);
|
||||
} else {
|
||||
m_image_grid->SetStatus(m_bmp_failed, _L("Connection Failed. Please check the network and try again"));
|
||||
std::string res = result.error_code >= 0 ? std::to_string(result.error_code) : "3";
|
||||
std::string res = "3";
|
||||
if (boost::ends_with(url, "]")) {
|
||||
size_t n = url.find_last_of('[');
|
||||
if (n != std::string::npos)
|
||||
res = url.substr(n + 1, url.length() - n - 2);
|
||||
}
|
||||
fs->SetUrl(res);
|
||||
}
|
||||
});
|
||||
},
|
||||
{URL_TUTK, "", "", "", m_machine, agent->get_version(), m_dev_ver,
|
||||
boost::lexical_cast<std::string>(&refresh_agora_url), wxGetApp().app_config->get("slicer_uuid"), SLIC3R_VERSION});
|
||||
}, wxGetApp().get_printer_cloud_provider());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ private:
|
||||
|
||||
std::string m_machine;
|
||||
std::string m_lan_ip;
|
||||
std::string m_lan_user;
|
||||
std::string m_lan_passwd;
|
||||
std::string m_dev_ver;
|
||||
bool m_lan_mode = false;
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
#include "I18N.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "DownloadProgressDialog.hpp"
|
||||
#include "slic3r/Utils/BBLNetworkPlugin.hpp"
|
||||
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#include <boost/nowide/utf8_codecvt.hpp>
|
||||
#include <slic3r/GUI/DeviceManager.hpp>
|
||||
#undef pid_t
|
||||
#include <boost/process.hpp>
|
||||
#ifdef __WIN32__
|
||||
@@ -126,6 +126,8 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const w
|
||||
parent->Bind(wxEVT_SHOW, &MediaPlayCtrl::on_show_hide, this);
|
||||
parent->GetParent()->GetParent()->Bind(wxEVT_SHOW, &MediaPlayCtrl::on_show_hide, this);
|
||||
|
||||
m_lan_user = "bblp";
|
||||
m_lan_passwd = "bblp";
|
||||
}
|
||||
|
||||
MediaPlayCtrl::~MediaPlayCtrl()
|
||||
@@ -156,16 +158,14 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
|
||||
m_device_busy = obj->is_camera_busy_off();
|
||||
m_tutk_state = obj->tutk_state;
|
||||
|
||||
auto *agent = wxGetApp().getAgent();
|
||||
if (agent && !agent->supports_remote_liveview(obj->printer_type)) {
|
||||
// The selected printer agent may force local mode for incompatible
|
||||
// plugin/printer combinations.
|
||||
m_remote_proto = LiveviewRemote::LVR_None;
|
||||
if (DevPrinterConfigUtil::get_printer_series_str(obj->printer_type) == "series_o" && BBLNetworkPlugin::instance().use_legacy_network()) {
|
||||
// Legacy plugin cannot support remote play for H2D, force using local mode
|
||||
m_remote_proto = MachineObject::LVR_None;
|
||||
}
|
||||
} else {
|
||||
m_camera_exists = false;
|
||||
m_lan_mode = false;
|
||||
m_lan_proto = LiveviewLocal::LVL_None;
|
||||
m_lan_proto = MachineObject::LVL_None;
|
||||
m_lan_ip.clear();
|
||||
m_lan_passwd.clear();
|
||||
m_dev_ver.clear();
|
||||
@@ -247,8 +247,8 @@ void refresh_agora_url(char const* device, char const* dev_ver, char const* chan
|
||||
device2 += dev_ver;
|
||||
device2 += "|\"agora\"|";
|
||||
device2 += channel;
|
||||
wxGetApp().getAgent()->get_camera_url(device2, [context, callback](CameraURLResult result) {
|
||||
callback(context, result.url.c_str());
|
||||
wxGetApp().getAgent()->get_camera_url(device2, [context, callback](std::string url) {
|
||||
callback(context, url.c_str());
|
||||
}, wxGetApp().get_printer_cloud_provider());
|
||||
}
|
||||
|
||||
@@ -282,26 +282,21 @@ void MediaPlayCtrl::Play()
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::Play: " << m_lan_proto << m_remote_proto << m_disable_lan;
|
||||
NetworkAgent *agent = wxGetApp().getAgent();
|
||||
if (!agent) {
|
||||
Stop(_L("Please confirm if the printer is connected."));
|
||||
return;
|
||||
}
|
||||
std::string agent_version = agent->get_version();
|
||||
const std::string lan_user = agent->default_lan_username();
|
||||
if (m_lan_proto > LiveviewLocal::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) {
|
||||
std::string agent_version = agent ? agent->get_version() : "";
|
||||
if (m_lan_proto > MachineObject::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) {
|
||||
m_disable_lan = m_remote_proto && !m_lan_mode; // try remote next time
|
||||
std::string url = agent->get_local_camera_url({
|
||||
m_lan_ip,
|
||||
lan_user,
|
||||
m_lan_passwd,
|
||||
LiveviewLocal(m_lan_proto),
|
||||
into_u8(m_machine),
|
||||
agent_version,
|
||||
m_dev_ver,
|
||||
"",
|
||||
wxGetApp().app_config->get("slicer_uuid"),
|
||||
SLIC3R_VERSION
|
||||
});
|
||||
std::string url;
|
||||
if (m_lan_proto == MachineObject::LVL_Local)
|
||||
url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
|
||||
else if (m_lan_proto == MachineObject::LVL_Rtsps)
|
||||
url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps";
|
||||
else if (m_lan_proto == MachineObject::LVL_Rtsp)
|
||||
url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp";
|
||||
url += "&device=" + m_machine;
|
||||
url += "&net_ver=" + agent_version;
|
||||
url += "&dev_ver=" + m_dev_ver;
|
||||
url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid");
|
||||
url += "&cli_ver=" + std::string(SLIC3R_VERSION);
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(hide_id_middle_string(url, url.find(m_lan_ip), m_lan_ip.length()), {m_lan_passwd});
|
||||
m_url = url;
|
||||
load();
|
||||
@@ -317,8 +312,8 @@ void MediaPlayCtrl::Play()
|
||||
// !m_lan_mode && !m_remote_proto && m_lan_proto == LVL_Disable (*)
|
||||
// !m_lan_mode && !m_remote_proto && m_lan_proto == LVL_None (x)
|
||||
|
||||
if (m_lan_proto <= LiveviewLocal::LVL_Disable && (m_lan_mode || !m_remote_proto)) {
|
||||
Stop(m_lan_proto == LiveviewLocal::LVL_None
|
||||
if (m_lan_proto <= MachineObject::LVL_Disable && (m_lan_mode || !m_remote_proto)) {
|
||||
Stop(m_lan_proto == MachineObject::LVL_None
|
||||
? _L("A problem occurred. Please update the printer firmware and try again.")
|
||||
: _L("LAN Only Liveview is off. Please turn on the liveview on printer screen."));
|
||||
return;
|
||||
@@ -341,39 +336,46 @@ void MediaPlayCtrl::Play()
|
||||
|
||||
if (agent) {
|
||||
std::string protocols[] = {"", "\"tutk\"", "\"agora\"", "\"tutk\",\"agora\""};
|
||||
agent->get_camera_url(
|
||||
m_machine + "|" + m_dev_ver + "|" + protocols[m_remote_proto],
|
||||
[this, m = m_machine, token = std::weak_ptr(m_token)](CameraURLResult result) {
|
||||
std::string url = std::move(result.url);
|
||||
const bool success = result.is_success;
|
||||
const int error_code = result.error_code;
|
||||
if (token.expired()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": token has been expired";
|
||||
agent->get_camera_url(m_machine + "|" + m_dev_ver + "|" + protocols[m_remote_proto],
|
||||
[this, m = m_machine, v = agent_version, dv = m_dev_ver, token = std::weak_ptr(m_token)](std::string url) {
|
||||
if (token.expired()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": token has been expired";
|
||||
return;
|
||||
}
|
||||
|
||||
if (boost::algorithm::starts_with(url, "bambu:///")) {
|
||||
url += "&device=" + into_u8(m);
|
||||
url += "&net_ver=" + v;
|
||||
url += "&dev_ver=" + dv;
|
||||
url += "&refresh_url=" + boost::lexical_cast<std::string>(&refresh_agora_url);
|
||||
url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid");
|
||||
url += "&cli_ver=" + std::string(SLIC3R_VERSION);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(url,
|
||||
{"?uid=", "authkey=", "passwd=", "license=", "token="});
|
||||
CallAfter([this, m, url] {
|
||||
if (m != m_machine) {
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for machine: " << m;
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(url, {"?uid=", "authkey=", "passwd=", "license=", "token="});
|
||||
CallAfter([this, m, url, success, error_code] {
|
||||
if (m != m_machine) {
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for machine: " << m;
|
||||
return;
|
||||
}
|
||||
if (m_last_state == MEDIASTATE_INITIALIZING) {
|
||||
if (!success) {
|
||||
m_failed_code = error_code >= 0 ? error_code : 3;
|
||||
Stop(_L("Connection Failed. Please check the network and try again"), from_u8(url));
|
||||
} else {
|
||||
m_url = url;
|
||||
load();
|
||||
if (m_last_state == MEDIASTATE_INITIALIZING) {
|
||||
if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) {
|
||||
m_failed_code = 3;
|
||||
if (boost::ends_with(url, "]")) {
|
||||
size_t n = url.find_last_of('[');
|
||||
if (n != std::string::npos)
|
||||
m_failed_code = std::atoi(url.substr(n + 1, url.length() - n - 2).c_str());
|
||||
}
|
||||
Stop(_L("Connection Failed. Please check the network and try again"), from_u8(url));
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for state: " << m_last_state;
|
||||
m_url = url;
|
||||
load();
|
||||
}
|
||||
});
|
||||
},
|
||||
wxGetApp().get_printer_cloud_provider(),
|
||||
CameraURLParams{"", "", "", LVL_None, into_u8(m_machine), agent_version, m_dev_ver,
|
||||
boost::lexical_cast<std::string>(&refresh_agora_url), wxGetApp().app_config->get("slicer_uuid"), SLIC3R_VERSION, true});
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for state: " << m_last_state;
|
||||
}
|
||||
});
|
||||
}, wxGetApp().get_printer_cloud_provider());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,11 +528,16 @@ void MediaPlayCtrl::ToggleStream()
|
||||
wxGetApp().app_config->set("not_show_vcamera_stop_prev", "1");
|
||||
if (res == wxID_CANCEL) return;
|
||||
}
|
||||
if (m_lan_proto > LiveviewLocal::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) {
|
||||
NetworkAgent *agent = wxGetApp().getAgent();
|
||||
if (!agent) return;
|
||||
std::string url = agent->get_local_camera_url({m_lan_ip, agent->default_lan_username(), m_lan_passwd, LiveviewLocal(m_lan_proto),
|
||||
into_u8(m_machine), agent->get_version(), m_dev_ver, "", wxGetApp().app_config->get("slicer_uuid"), SLIC3R_VERSION});
|
||||
if (m_lan_proto > MachineObject::LVL_Disable && (m_lan_mode || !m_remote_proto) && !m_disable_lan && !m_lan_ip.empty()) {
|
||||
std::string url;
|
||||
if (m_lan_proto == MachineObject::LVL_Local)
|
||||
url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
|
||||
else if (m_lan_proto == MachineObject::LVL_Rtsps)
|
||||
url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps";
|
||||
else if (m_lan_proto == MachineObject::LVL_Rtsp)
|
||||
url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp";
|
||||
url += "&device=" + into_u8(m_machine);
|
||||
url += "&dev_ver=" + m_dev_ver;
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(hide_id_middle_string(url, url.find(m_lan_ip), m_lan_ip.length()), {m_lan_passwd});
|
||||
std::string file_url = data_dir() + "/cameratools/url.txt";
|
||||
boost::nowide::ofstream file(file_url);
|
||||
@@ -544,14 +551,20 @@ void MediaPlayCtrl::ToggleStream()
|
||||
if (!agent) return;
|
||||
std::string protocols[] = {"", "\"tutk\"", "\"agora\"", "\"tutk\",\"agora\""};
|
||||
agent->get_camera_url(m_machine + "|" + m_dev_ver + "|" + protocols[m_remote_proto],
|
||||
[this, m = m_machine](CameraURLResult result) {
|
||||
std::string url = std::move(result.url);
|
||||
const bool success = result.is_success;
|
||||
[this, m = m_machine, v = agent->get_version(), dv = m_dev_ver](std::string url) {
|
||||
if (boost::algorithm::starts_with(url, "bambu:///")) {
|
||||
url += "&device=" + m;
|
||||
url += "&net_ver=" + v;
|
||||
url += "&dev_ver=" + dv;
|
||||
url += "&refresh_url=" + boost::lexical_cast<std::string>(&refresh_agora_url);
|
||||
url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid");
|
||||
url += "&cli_ver=" + std::string(SLIC3R_VERSION);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(url,
|
||||
{"?uid=", "authkey=", "passwd=", "license=", "token="});
|
||||
CallAfter([this, m, url, success] {
|
||||
CallAfter([this, m, url] {
|
||||
if (m != m_machine) return;
|
||||
if (!success) {
|
||||
if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) {
|
||||
MessageDialog(this->GetParent(), wxString::Format(_L("Virtual camera initialize failed (%s)!"), url.empty() ? _L("Network unreachable") : from_u8(url)), _L("Information"),
|
||||
wxICON_INFORMATION)
|
||||
.ShowModal();
|
||||
@@ -564,8 +577,7 @@ void MediaPlayCtrl::ToggleStream()
|
||||
file.close();
|
||||
m_streaming = true;
|
||||
});
|
||||
}, wxGetApp().get_printer_cloud_provider(), CameraURLParams{"", "", "", LVL_None, into_u8(m_machine), agent->get_version(), m_dev_ver,
|
||||
boost::lexical_cast<std::string>(&refresh_agora_url), wxGetApp().app_config->get("slicer_uuid"), SLIC3R_VERSION, true});
|
||||
}, wxGetApp().get_printer_cloud_provider());
|
||||
}
|
||||
|
||||
void MediaPlayCtrl::msw_rescale() {
|
||||
|
||||
@@ -80,6 +80,7 @@ private:
|
||||
std::string m_machine;
|
||||
int m_lan_proto = 0;
|
||||
std::string m_lan_ip;
|
||||
std::string m_lan_user;
|
||||
std::string m_lan_passwd;
|
||||
std::string m_dev_ver;
|
||||
std::string m_tutk_state;
|
||||
|
||||
@@ -433,38 +433,58 @@ void PartSkipDialog::fetchUrl(boost::weak_ptr<PrinterFileSystem> wfs)
|
||||
}
|
||||
std::string dev_ver = obj->get_ota_version();
|
||||
std::string dev_id = obj->get_dev_id();
|
||||
// int remote_proto = obj->get_file_remote();
|
||||
|
||||
NetworkAgent *agent = wxGetApp().getAgent();
|
||||
if (!agent) {
|
||||
fs->SetUrl("3");
|
||||
return;
|
||||
}
|
||||
NetworkAgent *agent = wxGetApp().getAgent();
|
||||
std::string agent_version = agent ? agent->get_version() : "";
|
||||
|
||||
auto url_state = m_url_state;
|
||||
if (obj->is_lan_mode_printer()) { url_state = URL_TCP; }
|
||||
|
||||
FileTransferURLParams params;
|
||||
params.url_state = url_state;
|
||||
params.ip_address = obj->get_dev_ip();
|
||||
params.username = agent->default_lan_username();
|
||||
params.password = obj->get_access_code();
|
||||
params.device_id = dev_id;
|
||||
params.network_version = agent->get_version();
|
||||
params.device_version = dev_ver;
|
||||
params.refresh_url = boost::lexical_cast<std::string>(&refresh_agora_url);
|
||||
params.client_id = wxGetApp().app_config->get("slicer_uuid");
|
||||
params.client_version = SLIC3R_VERSION;
|
||||
|
||||
agent->get_file_transfer_url(
|
||||
dev_id,
|
||||
[this, wfs](FileTransferURLResult result) {
|
||||
CallAfter([wfs, result = std::move(result)]() mutable {
|
||||
if (agent) {
|
||||
switch (url_state) {
|
||||
case URL_TCP: {
|
||||
std::string devIP = obj->get_dev_ip();
|
||||
std::string accessCode = obj->get_access_code();
|
||||
std::string tcp_url = "bambu:///local/" + devIP + "?port=6000&user=" + "bblp" + "&passwd=" + accessCode;
|
||||
CallAfter([=] {
|
||||
boost::shared_ptr fs(wfs.lock());
|
||||
if (!fs) return;
|
||||
fs->SetUrl(result.is_success ? result.url : "3");
|
||||
if (boost::algorithm::starts_with(tcp_url, "bambu:///")) {
|
||||
fs->SetUrl(tcp_url);
|
||||
} else {
|
||||
fs->SetUrl("3");
|
||||
}
|
||||
});
|
||||
},
|
||||
std::move(params));
|
||||
break;
|
||||
}
|
||||
case URL_TUTK: {
|
||||
std::string protocols[] = {"", "\"tutk\"", "\"agora\"", "\"tutk\",\"agora\""};
|
||||
agent->get_camera_url(obj->get_dev_id() + "|" + dev_ver + "|" + protocols[3], [this, wfs, m = dev_id, v = agent->get_version(), dv = dev_ver](std::string url)
|
||||
{
|
||||
if (boost::algorithm::starts_with(url, "bambu:///")) {
|
||||
url += "&device=" + m;
|
||||
url += "&net_ver=" + v;
|
||||
url += "&dev_ver=" + dv;
|
||||
url += "&refresh_url=" + boost::lexical_cast<std::string>(&refresh_agora_url);
|
||||
url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid");
|
||||
url += "&cli_ver=" + std::string(SLIC3R_VERSION);
|
||||
}
|
||||
CallAfter([=] {
|
||||
boost::shared_ptr fs(wfs.lock());
|
||||
if (!fs) return;
|
||||
if (boost::algorithm::starts_with(url, "bambu:///")) {
|
||||
fs->SetUrl(url);
|
||||
} else {
|
||||
fs->SetUrl("3");
|
||||
}
|
||||
});
|
||||
});
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// controller
|
||||
void PartSkipDialog::OnFileSystemEvent(wxCommandEvent &e)
|
||||
|
||||
@@ -29,6 +29,11 @@ namespace Slic3r { namespace GUI {
|
||||
|
||||
class SkipPartCanvas;
|
||||
|
||||
enum URL_STATE {
|
||||
URL_TCP,
|
||||
URL_TUTK,
|
||||
};
|
||||
|
||||
class PartSkipConfirmDialog : public DPIDialog
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -1801,8 +1801,6 @@ void InputIpAddressDialog::on_ok(wxMouseEvent& evt)
|
||||
m_trouble_shoot->Hide();
|
||||
std::string str_ip = m_input_ip->GetTextCtrl()->GetValue().ToStdString();
|
||||
std::string str_access_code = m_input_access_code->GetTextCtrl()->GetValue().ToStdString();
|
||||
if (str_access_code.empty())
|
||||
str_access_code = "88888888";
|
||||
std::string str_name = m_input_printer_name->GetTextCtrl()->GetValue().Strip(wxString::both).ToStdString();
|
||||
// Serial number should not contain lower case letters, and bambu_network plugin crashes
|
||||
// if user entered the wrong serial number, so we call `Upper()` here.
|
||||
@@ -1837,8 +1835,6 @@ void InputIpAddressDialog::on_send_retry()
|
||||
Fit();
|
||||
wxString ip = m_input_ip->GetTextCtrl()->GetValue();
|
||||
wxString str_access_code = m_input_access_code->GetTextCtrl()->GetValue();
|
||||
if (str_access_code.empty())
|
||||
str_access_code = "88888888";
|
||||
|
||||
// check support function
|
||||
if (!m_obj) return;
|
||||
@@ -2062,7 +2058,6 @@ void InputIpAddressDialog::on_text(wxCommandEvent &evt)
|
||||
|
||||
if (str_access_code.empty()) {
|
||||
str_access_code = "88888888";
|
||||
m_input_access_code->GetTextCtrl()->SetValue(str_access_code);
|
||||
}
|
||||
|
||||
auto str_name = m_input_printer_name->GetTextCtrl()->GetValue().Strip(wxString::both);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "SendToPrinter.hpp"
|
||||
#include "I18N.hpp"
|
||||
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Thread.hpp"
|
||||
#include "GUI.hpp"
|
||||
@@ -26,6 +25,7 @@
|
||||
|
||||
#include "DeviceCore/DevManager.h"
|
||||
#include "DeviceCore/DevStorage.h"
|
||||
#include "slic3r/Utils/FileTransferUtils.hpp"
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
@@ -845,8 +845,11 @@ void SendToPrinterDialog::on_ok(wxCommandEvent &event)
|
||||
m_task_timer.reset();
|
||||
}
|
||||
|
||||
if (auto agent = wxGetApp().getAgent(); agent && agent->get_printer_agent())
|
||||
agent->get_printer_agent()->cancel_file_transfer();
|
||||
if (m_filetransfer_uploadfile_job) {
|
||||
m_filetransfer_uploadfile_job->cancel();
|
||||
m_filetransfer_uploadfile_job.reset();
|
||||
m_filetransfer_uploadfile_job = nullptr;
|
||||
}
|
||||
|
||||
m_is_canceled = true;
|
||||
wxCommandEvent* event = new wxCommandEvent(EVT_PRINT_JOB_CANCEL);
|
||||
@@ -865,16 +868,16 @@ void SendToPrinterDialog::on_ok(wxCommandEvent &event)
|
||||
if (wxGetApp().plater()->using_exported_file()) {
|
||||
m_plater->set_print_job_plate_idx(m_print_plate_idx);
|
||||
result = 0;
|
||||
} else {
|
||||
result = m_plater->send_gcode(m_print_plate_idx, [this](int export_stage, int current, int total, bool& cancel) {
|
||||
if (this->m_is_canceled)
|
||||
return;
|
||||
bool cancelled = false;
|
||||
wxString msg = _L("Preparing print job");
|
||||
m_status_bar->update_status(msg, cancelled, 10, true);
|
||||
m_export_3mf_cancel = cancel = cancelled;
|
||||
});
|
||||
}
|
||||
else {
|
||||
result = m_plater->send_gcode(m_print_plate_idx, [this](int export_stage, int current, int total, bool &cancel) {
|
||||
if (this->m_is_canceled) return;
|
||||
bool cancelled = false;
|
||||
wxString msg = _L("Preparing print job");
|
||||
m_status_bar->update_status(msg, cancelled, 10, true);
|
||||
m_export_3mf_cancel = cancel = cancelled;
|
||||
});
|
||||
}
|
||||
|
||||
if (m_is_canceled || m_export_3mf_cancel) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": send progress 10";
|
||||
@@ -938,8 +941,7 @@ void SendToPrinterDialog::on_ok(wxCommandEvent &event)
|
||||
|
||||
this->Bind(wxEVT_TIMER, [this](auto e){
|
||||
show_status(PrintDialogStatus::PrintStatusPublicUploadFiled);
|
||||
if (auto agent = wxGetApp().getAgent(); agent && agent->get_printer_agent())
|
||||
agent->get_printer_agent()->cancel_file_transfer();
|
||||
m_filetransfer_uploadfile_job->cancel();
|
||||
update_print_status_msg(_L("Upload file timeout, please check if the firmware version supports it."), false, true);
|
||||
},m_task_timer->GetId());
|
||||
m_task_timer->StartOnce(timeout_period);
|
||||
@@ -1295,8 +1297,10 @@ void SendToPrinterDialog::update_show_status()
|
||||
else
|
||||
m_if_has_sdcard = true;
|
||||
|
||||
if (auto agent = wxGetApp().getAgent(); agent && agent->get_printer_agent())
|
||||
agent->get_printer_agent()->cancel_file_transfer();
|
||||
if (m_filetransfer_tunnel) {
|
||||
m_filetransfer_tunnel.reset();
|
||||
m_filetransfer_tunnel = nullptr;
|
||||
}
|
||||
|
||||
GetConnection();
|
||||
}
|
||||
@@ -1655,6 +1659,7 @@ bool SendToPrinterDialog::Show(bool show)
|
||||
return DPIDialog::Show(show);
|
||||
}
|
||||
|
||||
extern wxString hide_passwd(wxString url, std::vector<wxString> const &passwords);
|
||||
extern void refresh_agora_url(char const *device, char const *dev_ver, char const *channel, void *context, void (*callback)(void *context, char const *url));
|
||||
|
||||
void SendToPrinterDialog::GetConnection()
|
||||
@@ -1665,80 +1670,107 @@ void SendToPrinterDialog::GetConnection()
|
||||
if (obj == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " : obj is empty";
|
||||
m_connection_status = ConnectionStatus::NOT_START;
|
||||
return;
|
||||
}
|
||||
|
||||
int remote_proto = obj->get_file_remote();
|
||||
if (!remote_proto) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " : remote_proto is not support";
|
||||
m_connection_status = ConnectionStatus::NOT_START;
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->is_camera_busy_off()) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " : camera is busy";
|
||||
m_connection_status = ConnectionStatus::NOT_START;
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkAgent *agent = wxGetApp().getAgent();
|
||||
if (!agent || !agent->get_printer_agent()) {
|
||||
show_file_transfer_error(PrintDialogStatus::PrintStatusNotSupportedSendToSDCard,
|
||||
_L("The selected printer does not support file transfer."));
|
||||
return;
|
||||
NetworkAgent *agent = wxGetApp().getAgent();
|
||||
std::string agent_version = agent ? agent->get_version() : "";
|
||||
std::string dev_ver = obj->get_ota_version();
|
||||
std::string dev_id = obj->get_dev_id();
|
||||
|
||||
if (m_url_timer && m_url_timer->IsRunning())
|
||||
{
|
||||
m_url_timer->Stop();
|
||||
}
|
||||
|
||||
m_url_timer.reset(new wxTimer());
|
||||
m_url_timer->SetOwner(this);
|
||||
this->Bind(
|
||||
wxEVT_TIMER,
|
||||
[this](wxTimerEvent &e) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Timer callback triggered!";
|
||||
m_connection_status = ConnectionStatus::CONNECTION_FAILED;
|
||||
m_ftp_try_connect = true;
|
||||
if (m_filetransfer_tunnel)
|
||||
{
|
||||
m_filetransfer_tunnel.reset();
|
||||
m_filetransfer_tunnel = nullptr;
|
||||
}
|
||||
|
||||
},
|
||||
m_url_timer->GetId());
|
||||
m_url_timer->StartOnce(8000);
|
||||
|
||||
if (agent) {
|
||||
if (m_tcp_try_connect) {
|
||||
std::string devIP = obj->get_dev_ip();
|
||||
std::string accessCode = obj->get_access_code();
|
||||
std::string url = "bambu:///local/" + devIP + "?port=6000&user=" + "bblp" + "&passwd=" + accessCode;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Connect method tcp";
|
||||
m_filetransfer_tunnel = std::make_unique<FileTransferTunnel>(module(), url);
|
||||
m_filetransfer_tunnel->on_connection([this](bool is_success, int err_code, std::string error_msg) {
|
||||
CallAfter([this, is_success, err_code, error_msg]() {
|
||||
OnConnection(is_success, err_code, error_msg);
|
||||
});
|
||||
});
|
||||
m_filetransfer_tunnel->start_connect();
|
||||
}
|
||||
else if (m_tutk_try_connect)
|
||||
{
|
||||
std::string protocols[] = {"", "\"tutk\"", "\"agora\"", "\"tutk\",\"agora\""};
|
||||
agent->get_camera_url(obj->get_dev_id() + "|" + dev_ver + "|" + protocols[1], [this, m = dev_id, v = agent->get_version(), dv = dev_ver](std::string url) {
|
||||
if (boost::algorithm::starts_with(url, "bambu:///")) {
|
||||
url += "&device=" + m;
|
||||
url += "&net_ver=" + v;
|
||||
url += "&dev_ver=" + dv;
|
||||
url += "&refresh_url=" + boost::lexical_cast<std::string>(&refresh_agora_url);
|
||||
url += "&cli_id=" + wxGetApp().app_config->get("slicer_uuid");
|
||||
url += "&cli_ver=" + std::string(SLIC3R_VERSION);
|
||||
}
|
||||
|
||||
if (m_url_timer && m_url_timer->IsRunning())
|
||||
{
|
||||
m_url_timer->Stop();
|
||||
}
|
||||
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
BOOST_LOG_TRIVIAL(info) << "SendToPrinter::camera_url: " << hide_passwd(url, {"?uid=", "authkey=", "passwd="});
|
||||
#endif
|
||||
|
||||
|
||||
if (boost::algorithm::starts_with(url, "bambu:///"))
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Connect method tutk";
|
||||
m_filetransfer_tunnel = std::make_unique<FileTransferTunnel>(module(), url);
|
||||
m_filetransfer_tunnel->on_connection([this](bool is_success, int err_code, std::string error_msg) {
|
||||
CallAfter([this, is_success, err_code, error_msg]() { OnConnection(is_success, err_code, error_msg); });
|
||||
});
|
||||
m_filetransfer_tunnel->start_connect();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string res = "";
|
||||
if (!url.empty() && boost::ends_with(url, "]"))
|
||||
{
|
||||
size_t n = url.find_last_of('[');
|
||||
if (n != std::string::npos)
|
||||
res = url.substr(n + 1, url.length() - n - 2);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " : Tutk url error: ress = " << res;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (m_url_timer && m_url_timer->IsRunning()) {
|
||||
m_url_timer->Stop();
|
||||
}
|
||||
|
||||
m_url_timer.reset(new wxTimer());
|
||||
m_url_timer->SetOwner(this);
|
||||
this->Bind(
|
||||
wxEVT_TIMER,
|
||||
[this](wxTimerEvent& e) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Timer callback triggered!";
|
||||
m_connection_status = ConnectionStatus::CONNECTION_FAILED;
|
||||
m_ftp_try_connect = true;
|
||||
if (auto agent = wxGetApp().getAgent(); agent && agent->get_printer_agent())
|
||||
agent->get_printer_agent()->cancel_file_transfer();
|
||||
},
|
||||
m_url_timer->GetId());
|
||||
m_url_timer->StartOnce(8000);
|
||||
|
||||
IPrinterAgent::FileTransferRequest request;
|
||||
request.device_id = obj->get_dev_id();
|
||||
request.device_ip = obj->get_dev_ip();
|
||||
request.access_code = obj->get_access_code();
|
||||
request.network_version = agent->get_version();
|
||||
request.device_version = obj->get_ota_version();
|
||||
request.refresh_url = boost::lexical_cast<std::string>(&refresh_agora_url);
|
||||
request.client_id = wxGetApp().app_config->get("slicer_uuid");
|
||||
request.client_version = SLIC3R_VERSION;
|
||||
request.lan_mode = obj->connection_type() == "lan";
|
||||
|
||||
IPrinterAgent::FileTransferCallbacks callbacks;
|
||||
callbacks.on_connection = [this](bool is_success, int error_code, std::string error_msg) {
|
||||
CallAfter([this, is_success, error_code, error_msg = std::move(error_msg)] {
|
||||
OnConnection(is_success, error_code, std::move(error_msg));
|
||||
});
|
||||
};
|
||||
callbacks.file_transfer_error = [this] {
|
||||
CallAfter([this] {
|
||||
show_file_transfer_error(PrintDialogStatus::PrintStatusNotSupportedSendToSDCard,
|
||||
_L("The selected printer does not support file transfer."));
|
||||
});
|
||||
};
|
||||
agent->get_printer_agent()->prepare_file_transfer(request, std::move(callbacks));
|
||||
}
|
||||
|
||||
void SendToPrinterDialog::show_file_transfer_error(PrintDialogStatus status, wxString message)
|
||||
{
|
||||
if (m_url_timer && m_url_timer->IsRunning())
|
||||
m_url_timer->Stop();
|
||||
m_connection_status = ConnectionStatus::CONNECTION_FAILED;
|
||||
show_status(status);
|
||||
update_print_status_msg(message, false, true);
|
||||
}
|
||||
|
||||
void SendToPrinterDialog::OnConnection(bool is_success, int error_code, std::string error_msg) {
|
||||
@@ -1753,13 +1785,43 @@ void SendToPrinterDialog::OnConnection(bool is_success, int error_code, std::str
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Connect failed, error_code is:" << error_code << "error_msg is :" << error_msg;
|
||||
m_connection_status = ConnectionStatus::CONNECTION_FAILED;
|
||||
m_tcp_try_connect = false;
|
||||
m_tutk_try_connect = false;
|
||||
m_ftp_try_connect = true;
|
||||
show_status(PrintDialogStatus::PrintStatusPublicInitFailed);
|
||||
ChangeConnectMethod();
|
||||
if (!m_tcp_try_connect && !m_tutk_try_connect) {
|
||||
show_status(PrintDialogStatus::PrintStatusPublicInitFailed);
|
||||
return;
|
||||
}
|
||||
m_filetransfer_tunnel.reset();
|
||||
m_filetransfer_tunnel = nullptr;
|
||||
GetConnection();
|
||||
}
|
||||
}
|
||||
|
||||
void SendToPrinterDialog::ChangeConnectMethod()
|
||||
{
|
||||
DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (!dev) return;
|
||||
MachineObject *obj = dev->get_my_machine(m_printer_last_select);
|
||||
if (!obj) return;
|
||||
|
||||
bool is_lan = (obj->connection_type() == "lan");
|
||||
|
||||
m_tcp_try_connect = false;
|
||||
|
||||
if (is_lan) {
|
||||
m_ftp_try_connect = true;
|
||||
m_tutk_try_connect = false;
|
||||
} else {
|
||||
if (m_connect_try_times == 0) {
|
||||
m_ftp_try_connect = false;
|
||||
m_tutk_try_connect = true;
|
||||
} else {
|
||||
m_ftp_try_connect = true;
|
||||
m_tutk_try_connect = false;
|
||||
}
|
||||
}
|
||||
m_connect_try_times++;
|
||||
}
|
||||
|
||||
void SendToPrinterDialog::ResetConnectMethod()
|
||||
{
|
||||
m_tcp_try_connect = true;
|
||||
@@ -1771,21 +1833,32 @@ void SendToPrinterDialog::ResetConnectMethod()
|
||||
|
||||
void SendToPrinterDialog::ResetTunnelAndJob()
|
||||
{
|
||||
if (auto agent = wxGetApp().getAgent(); agent && agent->get_printer_agent())
|
||||
agent->get_printer_agent()->cancel_file_transfer();
|
||||
if (m_filetransfer_uploadfile_job)
|
||||
{
|
||||
m_filetransfer_uploadfile_job->cancel();
|
||||
m_filetransfer_uploadfile_job.reset();
|
||||
m_filetransfer_uploadfile_job = nullptr;
|
||||
}
|
||||
if (m_filetransfer_mediability_job)
|
||||
{
|
||||
m_filetransfer_mediability_job->cancel();
|
||||
m_filetransfer_mediability_job.reset();
|
||||
m_filetransfer_mediability_job = nullptr;
|
||||
}
|
||||
if (m_filetransfer_tunnel)
|
||||
{
|
||||
m_filetransfer_tunnel.reset();
|
||||
m_filetransfer_tunnel = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SendToPrinterDialog::CreateMediaAbilityJob()
|
||||
{
|
||||
NetworkAgent *agent = wxGetApp().getAgent();
|
||||
if (!agent || !agent->get_printer_agent()) {
|
||||
show_file_transfer_error(PrintDialogStatus::PrintStatusNotSupportedSendToSDCard,
|
||||
_L("The selected printer does not support file transfer."));
|
||||
return;
|
||||
}
|
||||
IPrinterAgent::FileTransferCallbacks callbacks;
|
||||
callbacks.on_destinations = [this](int res, int resp_ec, std::string json_res) {
|
||||
CallAfter([this, res, resp_ec, json_res = std::move(json_res)] {
|
||||
nlohmann::json media_ability = {{"cmd_type", 7}};
|
||||
m_filetransfer_mediability_job = std::make_unique<FileTransferJob>(module(), std::string(media_ability.dump()));
|
||||
m_filetransfer_mediability_job->on_result([this](int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res) {
|
||||
//this pl
|
||||
CallAfter([this, res, resp_ec, json_res] {
|
||||
if (res == 0) // 0 is success
|
||||
{
|
||||
show_status(PrintDialogStatus::PrintStatusReadingFinished);
|
||||
@@ -1821,41 +1894,59 @@ void SendToPrinterDialog::CreateMediaAbilityJob()
|
||||
show_status(PrintDialogStatus::PrintStatusPublicInitFailed);
|
||||
update_print_status_msg(ParseErrorCode(resp_ec), false, true);
|
||||
}
|
||||
});
|
||||
};
|
||||
callbacks.file_transfer_error = [this] {
|
||||
CallAfter([this] {
|
||||
show_file_transfer_error(PrintDialogStatus::PrintStatusNotSupportedSendToSDCard,
|
||||
_L("The selected printer does not support file transfer."));
|
||||
});
|
||||
};
|
||||
agent->get_printer_agent()->get_file_destinations(std::move(callbacks));
|
||||
});
|
||||
});
|
||||
// Guard against a null transfer tunnel before dereferencing.
|
||||
if (m_filetransfer_tunnel) {
|
||||
m_filetransfer_mediability_job->start_on(*m_filetransfer_tunnel);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "CreateMediaAbilityJob: file transfer tunnel is null";
|
||||
}
|
||||
}
|
||||
|
||||
void SendToPrinterDialog::CreateUploadFileJob(const std::string &path, const std::string &name)
|
||||
{
|
||||
NetworkAgent *agent = wxGetApp().getAgent();
|
||||
if (!agent || !agent->get_printer_agent()) {
|
||||
show_file_transfer_error(PrintDialogStatus::PrintStatusPublicUploadFiled,
|
||||
_L("The selected printer does not support file transfer."));
|
||||
return;
|
||||
nlohmann::json upload_params = {
|
||||
{"cmd_type", 5},
|
||||
};
|
||||
upload_params["dest_storage"] = m_selected_storage;
|
||||
upload_params["dest_name"] = name; // filenme no path
|
||||
upload_params["file_path"] = path;
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Begin CreateUploadFileJob";
|
||||
m_filetransfer_uploadfile_job = std::make_unique<FileTransferJob>(module(), std::string(upload_params.dump()));
|
||||
m_filetransfer_uploadfile_job->on_result([this](int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res) { //
|
||||
CallAfter([this, res, resp_ec, json_res, bin_res] {
|
||||
UploadFileRessultCallback(res, resp_ec,json_res, bin_res);
|
||||
});
|
||||
});
|
||||
|
||||
m_filetransfer_uploadfile_job->on_msg([this](int kind, std::string json_res) {
|
||||
CallAfter([this, kind, json_res] {
|
||||
if (kind == 0) {
|
||||
try
|
||||
{
|
||||
auto js = nlohmann::json::parse(json_res);
|
||||
int progress = js["progress"].get<int>();
|
||||
UploadFileProgressCallback(progress);
|
||||
}
|
||||
catch (const nlohmann::json::exception& e)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << e.what();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << "parse_json failed! ";
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
// Guard against a null transfer tunnel before dereferencing.
|
||||
if (m_filetransfer_tunnel) {
|
||||
m_filetransfer_uploadfile_job->start_on(*m_filetransfer_tunnel);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": file transfer tunnel is null";
|
||||
}
|
||||
IPrinterAgent::FileTransferCallbacks callbacks;
|
||||
callbacks.on_progress = [this](int progress) {
|
||||
CallAfter([this, progress] { UploadFileProgressCallback(progress); });
|
||||
};
|
||||
callbacks.on_result = [this](int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res) {
|
||||
CallAfter([this, res, resp_ec, json_res = std::move(json_res), bin_res = std::move(bin_res)] {
|
||||
UploadFileRessultCallback(res, resp_ec, std::move(json_res), std::move(bin_res));
|
||||
});
|
||||
};
|
||||
callbacks.file_transfer_error = [this] {
|
||||
CallAfter([this] {
|
||||
show_file_transfer_error(PrintDialogStatus::PrintStatusPublicUploadFiled,
|
||||
_L("The selected printer does not support file transfer."));
|
||||
});
|
||||
};
|
||||
agent->get_printer_agent()->upload_file(path, name, m_selected_storage, std::move(callbacks));
|
||||
}
|
||||
|
||||
void SendToPrinterDialog::UploadFileProgressCallback(int progress)
|
||||
@@ -1874,8 +1965,6 @@ void SendToPrinterDialog::UploadFileProgressCallback(int progress)
|
||||
wxEVT_TIMER,
|
||||
[this](auto e) {
|
||||
show_status(PrintDialogStatus::PrintStatusPublicUploadFiled);
|
||||
if (auto agent = wxGetApp().getAgent(); agent && agent->get_printer_agent())
|
||||
agent->get_printer_agent()->cancel_file_transfer();
|
||||
update_print_status_msg(
|
||||
_L("File upload timed out. Please check if the firmware version supports this operation or verify if the printer is functioning properly."), false, true);
|
||||
},
|
||||
@@ -1904,6 +1993,8 @@ void SendToPrinterDialog::UploadFileRessultCallback(int res, int resp_ec, std::s
|
||||
update_print_status_msg(ParseErrorCode(resp_ec), false, true);
|
||||
else
|
||||
update_print_status_msg(_L("Sending failed, please try again!"), false, true);
|
||||
m_filetransfer_uploadfile_job.reset();
|
||||
m_filetransfer_uploadfile_job = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <wx/wrapsizer.h>
|
||||
#include <wx/srchctrl.h>
|
||||
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "SelectMachine.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
@@ -44,6 +43,8 @@
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
class FileTransferTunnel;
|
||||
class FileTransferJob;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
@@ -170,6 +171,9 @@ private:
|
||||
enum ConnectionStatus { NOT_START, CONNECTING, CONNECTED, CONNECTION_FAILED, DISCONNECTED };
|
||||
ConnectionStatus m_connection_status{ConnectionStatus::NOT_START};
|
||||
|
||||
std::unique_ptr<FileTransferTunnel> m_filetransfer_tunnel;
|
||||
std::unique_ptr<FileTransferJob> m_filetransfer_mediability_job;
|
||||
std::unique_ptr<FileTransferJob> m_filetransfer_uploadfile_job;
|
||||
wxDateTime m_last_refresh_time;
|
||||
|
||||
public:
|
||||
@@ -219,10 +223,10 @@ public:
|
||||
private:
|
||||
void ResetConnectMethod();
|
||||
void ResetTunnelAndJob();
|
||||
void show_file_transfer_error(PrintDialogStatus status, wxString message);
|
||||
void OnConnection(bool is_success, int error_code, std::string error_msg);
|
||||
void CreateMediaAbilityJob();
|
||||
void CreateUploadFileJob(const std::string &path, const std::string &name);
|
||||
void ChangeConnectMethod();
|
||||
void UploadFileProgressCallback(int progress);
|
||||
void UploadFileRessultCallback(int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res);
|
||||
void Reset();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "BBLCloudServiceAgent.hpp"
|
||||
#include "BBLNetworkPlugin.hpp"
|
||||
#include "NetworkAgent.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include "Http.hpp"
|
||||
@@ -607,47 +606,13 @@ int BBLCloudServiceAgent::modify_printer_name(std::string dev_id, std::string de
|
||||
// Model Mall & Publishing
|
||||
// ============================================================================
|
||||
|
||||
int BBLCloudServiceAgent::get_camera_url(std::string dev_id, std::function<void(CameraURLResult)> callback, CameraURLParams params)
|
||||
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) {
|
||||
auto make_result = [](std::string url) {
|
||||
CameraURLResult result;
|
||||
result.url = std::move(url);
|
||||
result.is_success = result.url.rfind("bambu:///", 0) == 0;
|
||||
if (result.is_success) {
|
||||
result.error_code = 0;
|
||||
} else if (!result.url.empty() && result.url.back() == ']') {
|
||||
const auto start = result.url.rfind('[');
|
||||
if (start != std::string::npos && start + 1 < result.url.size() - 1) {
|
||||
try {
|
||||
result.error_code = std::stoi(result.url.substr(start + 1, result.url.size() - start - 2));
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
if (params.apply_meta) {
|
||||
auto decorated_callback = [callback = std::move(callback), params = std::move(params), make_result](std::string url) {
|
||||
CameraURLResult result = make_result(std::move(url));
|
||||
if (result.is_success) {
|
||||
result.url += "&device=" + params.device;
|
||||
result.url += "&net_ver=" + params.network_version;
|
||||
result.url += "&dev_ver=" + params.device_version;
|
||||
result.url += "&refresh_url=" + params.refresh_url;
|
||||
result.url += "&cli_id=" + params.client_id;
|
||||
result.url += "&cli_ver=" + params.client_version;
|
||||
}
|
||||
callback(std::move(result));
|
||||
};
|
||||
return func(agent, std::move(dev_id), std::move(decorated_callback));
|
||||
}
|
||||
return func(agent, std::move(dev_id), [callback = std::move(callback), make_result](std::string url) {
|
||||
callback(make_result(std::move(url)));
|
||||
});
|
||||
return func(agent, dev_id, callback);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
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(CameraURLResult)> callback, CameraURLParams params) override;
|
||||
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;
|
||||
|
||||
@@ -1,405 +1,15 @@
|
||||
#include "BBLPrinterAgent.hpp"
|
||||
#include "BBLNetworkPlugin.hpp"
|
||||
#include "FileTransferUtils.hpp"
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "NetworkAgentFactory.hpp"
|
||||
#include "NetworkAgent.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <memory>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <cmath>
|
||||
#include <slic3r/GUI/DeviceManager.hpp>
|
||||
#include <libslic3r/Utils.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// ============================================================================
|
||||
// File Transfer (Bambu eMMC tunnel ABI)
|
||||
// ============================================================================
|
||||
|
||||
BBLFileTransferTunnel::BBLFileTransferTunnel(const std::string &url) : IFileTransferTunnel(url)
|
||||
{
|
||||
FileTransferModule &m = module();
|
||||
m_ = &m;
|
||||
// Guard against missing symbols in older Bambu networking plugins.
|
||||
// These symbols were added in a newer plugin ABI; if the installed
|
||||
// plugin predates them, ft_tunnel_create/ft_tunnel_set_status_cb
|
||||
// will be null and calling them crashes.
|
||||
if (!m_->ft_tunnel_create || !m_->ft_tunnel_set_status_cb) {
|
||||
throw std::runtime_error("Bambu networking plugin is too old: missing ft_tunnel_* symbols. "
|
||||
"Please update the networking plugin.");
|
||||
}
|
||||
FT_TunnelHandle *h{};
|
||||
if (m_->ft_tunnel_create(url.c_str(), &h) != 0 || !h) {
|
||||
throw std::runtime_error("ft_tunnel_create failed");
|
||||
}
|
||||
h_ = h;
|
||||
|
||||
// C API: ft_status_cb(void* user, int old_status, int new_status, int err, const char* msg)
|
||||
auto tramp = [](void *user, int old_status, int new_status, int err_code, const char *msg) noexcept {
|
||||
auto *self = reinterpret_cast<BBLFileTransferTunnel *>(user);
|
||||
self->status_ = new_status;
|
||||
if (!self->status_cb_) return;
|
||||
try {
|
||||
self->status_cb_(old_status, new_status, err_code, std::string(msg ? msg : ""));
|
||||
} catch (...) {}
|
||||
};
|
||||
if (m_->ft_tunnel_set_status_cb(h_, tramp, this) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_tunnel_set_status_cb failed"); }
|
||||
}
|
||||
|
||||
void BBLFileTransferTunnel::start_connect()
|
||||
{
|
||||
// C API: ft_conn_cb(void* user, int ok, int err, const char* msg)
|
||||
auto tramp = [](void *user, int ok, int ec, const char *msg) noexcept {
|
||||
auto *pcb = reinterpret_cast<ConnectionCb *>(user);
|
||||
if (!pcb) return;
|
||||
try {
|
||||
(*pcb)(ok == 0, ec, std::string(msg ? msg : ""));
|
||||
} catch (...) {}
|
||||
};
|
||||
if (m_->ft_tunnel_start_connect(h_, tramp, &conn_cb_) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_tunnel_start_connect failed"); }
|
||||
}
|
||||
|
||||
bool BBLFileTransferTunnel::sync_start_connect()
|
||||
{
|
||||
return m_->ft_tunnel_sync_connect(h_) == FT_OK;
|
||||
}
|
||||
|
||||
void BBLFileTransferTunnel::shutdown()
|
||||
{
|
||||
if (m_->ft_tunnel_shutdown) (void) m_->ft_tunnel_shutdown(h_);
|
||||
}
|
||||
|
||||
BBLFileTransferJob::BBLFileTransferJob(const std::string ¶ms_json) : IFileTransferJob(params_json)
|
||||
{
|
||||
m_ = &module();
|
||||
FT_JobHandle *h{};
|
||||
if (m_->ft_job_create(params_json.c_str(), &h) != 0 || !h) {
|
||||
throw std::runtime_error("ft_job_create failed");
|
||||
}
|
||||
h_ = h;
|
||||
|
||||
// C API: ft_job_result_cb(void* user, int tunnel_err, ft_job_result result)
|
||||
auto tramp = [](void *user, ft_job_result r) noexcept {
|
||||
auto *self = reinterpret_cast<BBLFileTransferJob *>(user);
|
||||
if (!self) return;
|
||||
|
||||
try {
|
||||
self->finished_ = true;
|
||||
self->solve_result(r);
|
||||
if (self->result_cb_) self->result_cb_(self->res_, self->resp_ec_, self->res_json_, self->res_bin_);
|
||||
} catch (...) {
|
||||
// swallow
|
||||
}
|
||||
|
||||
try {
|
||||
if (auto *mod = self ? self->m_ : nullptr) {
|
||||
if (mod->ft_job_result_destroy)
|
||||
mod->ft_job_result_destroy(&r);
|
||||
else if (mod->ft_free) {
|
||||
if (r.json) mod->ft_free((void *) r.json);
|
||||
if (r.bin) mod->ft_free((void *) r.bin);
|
||||
}
|
||||
}
|
||||
} catch (...) {}
|
||||
};
|
||||
|
||||
if (m_->ft_job_set_result_cb(h_, tramp, this) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_job_set_result_cb failed"); }
|
||||
}
|
||||
|
||||
bool BBLFileTransferJob::get_result(int &ec, int &resp_ec, std::string &json, std::vector<std::byte> &bin, uint32_t timeout_ms)
|
||||
{
|
||||
if (!h_) throw std::runtime_error("job handle invalid");
|
||||
ft_job_result result;
|
||||
if (m_->ft_job_get_result(h_, timeout_ms, &result) == ft_err::FT_EXCEPTION) return false;
|
||||
solve_result(result);
|
||||
m_->ft_job_result_destroy(&result);
|
||||
ec = res_;
|
||||
resp_ec = res_;
|
||||
json = res_json_;
|
||||
bin = res_bin_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void BBLFileTransferJob::start_on(IFileTransferTunnel &t)
|
||||
{
|
||||
if (!h_) throw std::runtime_error("job handle invalid");
|
||||
auto *handle = reinterpret_cast<FT_TunnelHandle *>(t.native());
|
||||
if (m_->ft_tunnel_start_job(handle, h_) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_tunnel_start_job failed"); }
|
||||
}
|
||||
|
||||
void BBLFileTransferJob::on_msg(MsgCb cb)
|
||||
{
|
||||
IFileTransferJob::on_msg(std::move(cb));
|
||||
if (!h_) return;
|
||||
|
||||
// C API: ft_job_msg_cb(void* user, ft_job_msg msg)
|
||||
auto tramp = [](void *user, ft_job_msg m) noexcept {
|
||||
auto *self = reinterpret_cast<BBLFileTransferJob *>(user);
|
||||
if (!self) return;
|
||||
try {
|
||||
if (self->msg_cb_) { self->msg_cb_(m.kind, std::string(m.json ? m.json : "")); }
|
||||
} catch (...) {}
|
||||
|
||||
try {
|
||||
if (auto *mod = self->m_) {
|
||||
if (mod->ft_job_msg_destroy)
|
||||
mod->ft_job_msg_destroy(&m);
|
||||
else if (mod->ft_free && m.json)
|
||||
mod->ft_free((void *) m.json);
|
||||
}
|
||||
} catch (...) {}
|
||||
};
|
||||
|
||||
if (m_->ft_job_set_msg_cb(h_, tramp, this) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_job_set_msg_cb failed"); }
|
||||
}
|
||||
|
||||
bool BBLFileTransferJob::try_get_msg(int &kind, std::string &json)
|
||||
{
|
||||
if (!h_) return false;
|
||||
ft_job_msg m{};
|
||||
int rc = m_->ft_job_try_get_msg(h_, &m);
|
||||
if (rc != 0) return false;
|
||||
|
||||
kind = m.kind;
|
||||
json.assign(m.json ? m.json : "");
|
||||
|
||||
if (m_->ft_job_msg_destroy)
|
||||
m_->ft_job_msg_destroy(&m);
|
||||
else if (m_->ft_free && m.json)
|
||||
m_->ft_free((void *) m.json);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BBLFileTransferJob::get_msg(uint32_t timeout_ms, int &kind, std::string &json)
|
||||
{
|
||||
if (!h_) return false;
|
||||
ft_job_msg m{};
|
||||
int rc = m_->ft_job_get_msg(h_, timeout_ms, &m);
|
||||
if (rc != 0) return false;
|
||||
|
||||
kind = m.kind;
|
||||
json.assign(m.json ? m.json : "");
|
||||
|
||||
if (m_->ft_job_msg_destroy)
|
||||
m_->ft_job_msg_destroy(&m);
|
||||
else if (m_->ft_free && m.json)
|
||||
m_->ft_free((void *) m.json);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BBLFileTransferJob::solve_result(ft_job_result result)
|
||||
{
|
||||
res_ = result.ec;
|
||||
resp_ec_ = result.resp_ec;
|
||||
|
||||
res_bin_.clear();
|
||||
if (result.bin && result.bin_size) res_bin_.assign(reinterpret_cast<const std::byte *>(result.bin),
|
||||
reinterpret_cast<const std::byte *>(result.bin) + result.bin_size);
|
||||
res_json_.assign(result.json ? result.json : "");
|
||||
}
|
||||
|
||||
BBLPrinterAgent::BBLPrinterAgent() = default;
|
||||
|
||||
BBLPrinterAgent::~BBLPrinterAgent() = default;
|
||||
|
||||
void BBLPrinterAgent::prepare_file_transfer(const FileTransferRequest& request, FileTransferCallbacks cb)
|
||||
{
|
||||
cancel_file_transfer();
|
||||
m_file_transfer_request = request;
|
||||
m_file_transfer_callbacks = std::move(cb);
|
||||
m_file_transfer_tcp = true;
|
||||
m_file_transfer_try_count = 0;
|
||||
start_file_transfer_attempt(++m_file_transfer_generation);
|
||||
}
|
||||
|
||||
void BBLPrinterAgent::start_file_transfer_attempt(uint64_t generation)
|
||||
{
|
||||
FileTransferURLParams params;
|
||||
params.url_state = m_file_transfer_tcp ? URL_TCP : URL_TUTK;
|
||||
params.ip_address = m_file_transfer_request.device_ip;
|
||||
params.username = default_lan_username();
|
||||
params.password = m_file_transfer_request.access_code;
|
||||
params.device_id = m_file_transfer_request.device_id;
|
||||
params.network_version = m_file_transfer_request.network_version;
|
||||
params.device_version = m_file_transfer_request.device_version;
|
||||
params.refresh_url = m_file_transfer_request.refresh_url;
|
||||
params.client_id = m_file_transfer_request.client_id;
|
||||
params.client_version = m_file_transfer_request.client_version;
|
||||
|
||||
auto handle_url = [this, generation](FileTransferURLResult result) {
|
||||
if (generation != m_file_transfer_generation)
|
||||
return;
|
||||
if (!result.is_success) {
|
||||
handle_file_transfer_connection(generation, false, result.error_code, "file-transfer URL unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
m_file_transfer_tunnel = std::make_unique<BBLFileTransferTunnel>(result.url);
|
||||
} catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "BBLPrinterAgent: failed to create file-transfer tunnel: " << e.what();
|
||||
m_file_transfer_tunnel.reset();
|
||||
}
|
||||
|
||||
if (!m_file_transfer_tunnel || !m_file_transfer_tunnel->check_valid()) {
|
||||
handle_file_transfer_connection(generation, false, -1, "file-transfer tunnel unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
m_file_transfer_tunnel->on_connection([this, generation](bool is_success, int error_code, std::string error_msg) {
|
||||
handle_file_transfer_connection(generation, is_success, error_code, std::move(error_msg));
|
||||
});
|
||||
m_file_transfer_tunnel->start_connect();
|
||||
};
|
||||
|
||||
if (m_file_transfer_tcp) {
|
||||
get_file_transfer_url(m_file_transfer_request.device_id, std::move(handle_url), params);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_cloud_agent) {
|
||||
handle_file_transfer_connection(generation, false, -1, "cloud file-transfer URL unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string protocols = "\"tutk\"";
|
||||
m_cloud_agent->get_camera_url(
|
||||
m_file_transfer_request.device_id + "|" + m_file_transfer_request.device_version + "|" + protocols,
|
||||
[handle_url = std::move(handle_url)](CameraURLResult result) mutable {
|
||||
FileTransferURLResult transfer_result;
|
||||
transfer_result.is_success = result.is_success;
|
||||
transfer_result.url = std::move(result.url);
|
||||
transfer_result.error_code = result.error_code;
|
||||
handle_url(std::move(transfer_result));
|
||||
},
|
||||
CameraURLParams{
|
||||
"", "", "", LVL_None,
|
||||
m_file_transfer_request.device_id,
|
||||
m_file_transfer_request.network_version,
|
||||
m_file_transfer_request.device_version,
|
||||
m_file_transfer_request.refresh_url,
|
||||
m_file_transfer_request.client_id,
|
||||
m_file_transfer_request.client_version,
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
void BBLPrinterAgent::handle_file_transfer_connection(uint64_t generation, bool is_success, int error_code, std::string error_msg)
|
||||
{
|
||||
if (generation != m_file_transfer_generation)
|
||||
return;
|
||||
if (is_success) {
|
||||
if (m_file_transfer_callbacks.on_connection)
|
||||
m_file_transfer_callbacks.on_connection(true, error_code, std::move(error_msg));
|
||||
return;
|
||||
}
|
||||
|
||||
// Preserve the existing dialog fallback order: TCP, then TUTK for cloud
|
||||
// printers, and finally the legacy FTP path handled by SendJob.
|
||||
m_file_transfer_tunnel.reset();
|
||||
if (!m_file_transfer_request.lan_mode && m_file_transfer_tcp && m_file_transfer_try_count == 0) {
|
||||
m_file_transfer_tcp = false;
|
||||
++m_file_transfer_try_count;
|
||||
start_file_transfer_attempt(generation);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_file_transfer_callbacks.on_connection)
|
||||
m_file_transfer_callbacks.on_connection(false, error_code, std::move(error_msg));
|
||||
}
|
||||
|
||||
void BBLPrinterAgent::get_file_destinations(FileTransferCallbacks cb)
|
||||
{
|
||||
if (!m_file_transfer_tunnel || !m_file_transfer_tunnel->check_valid()) {
|
||||
if (cb.file_transfer_error)
|
||||
cb.file_transfer_error();
|
||||
return;
|
||||
}
|
||||
|
||||
nlohmann::json params = {{"cmd_type", 7}};
|
||||
try {
|
||||
m_file_transfer_job = std::make_unique<BBLFileTransferJob>(params.dump());
|
||||
} catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "BBLPrinterAgent: failed to create media-ability job: " << e.what();
|
||||
m_file_transfer_job.reset();
|
||||
}
|
||||
|
||||
if (!m_file_transfer_job || !m_file_transfer_job->check_valid()) {
|
||||
if (cb.file_transfer_error)
|
||||
cb.file_transfer_error();
|
||||
return;
|
||||
}
|
||||
|
||||
m_file_transfer_job->on_result([cb = std::move(cb)](int result, int response_error, std::string json_result,
|
||||
std::vector<std::byte>) {
|
||||
if (cb.on_destinations)
|
||||
cb.on_destinations(result, response_error, std::move(json_result));
|
||||
});
|
||||
m_file_transfer_job->start_on(*m_file_transfer_tunnel);
|
||||
}
|
||||
|
||||
void BBLPrinterAgent::upload_file(const std::string& path, const std::string& name, const std::string& destination,
|
||||
FileTransferCallbacks cb)
|
||||
{
|
||||
if (!m_file_transfer_tunnel || !m_file_transfer_tunnel->check_valid()) {
|
||||
if (cb.file_transfer_error)
|
||||
cb.file_transfer_error();
|
||||
return;
|
||||
}
|
||||
|
||||
nlohmann::json params = {
|
||||
{"cmd_type", 5},
|
||||
{"dest_storage", destination},
|
||||
{"dest_name", name},
|
||||
{"file_path", path}
|
||||
};
|
||||
|
||||
try {
|
||||
m_file_transfer_job = std::make_unique<BBLFileTransferJob>(params.dump());
|
||||
} catch (const std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "BBLPrinterAgent: failed to create upload job: " << e.what();
|
||||
m_file_transfer_job.reset();
|
||||
}
|
||||
|
||||
if (!m_file_transfer_job || !m_file_transfer_job->check_valid()) {
|
||||
if (cb.file_transfer_error)
|
||||
cb.file_transfer_error();
|
||||
return;
|
||||
}
|
||||
|
||||
auto callbacks = std::make_shared<FileTransferCallbacks>(std::move(cb));
|
||||
m_file_transfer_job->on_result([callbacks](int result, int response_error, std::string json_result,
|
||||
std::vector<std::byte> binary_result) {
|
||||
if (callbacks->on_result)
|
||||
callbacks->on_result(result, response_error, std::move(json_result), std::move(binary_result));
|
||||
});
|
||||
m_file_transfer_job->on_msg([callbacks](int kind, std::string json_result) {
|
||||
if (kind == 0 && callbacks->on_progress) {
|
||||
try {
|
||||
callbacks->on_progress(nlohmann::json::parse(json_result).at("progress").get<int>());
|
||||
} catch (...) {
|
||||
BOOST_LOG_TRIVIAL(error) << "BBLPrinterAgent: failed to parse upload progress";
|
||||
}
|
||||
}
|
||||
});
|
||||
m_file_transfer_job->start_on(*m_file_transfer_tunnel);
|
||||
}
|
||||
|
||||
void BBLPrinterAgent::cancel_file_transfer()
|
||||
{
|
||||
++m_file_transfer_generation;
|
||||
if (m_file_transfer_job)
|
||||
m_file_transfer_job->cancel();
|
||||
m_file_transfer_job.reset();
|
||||
m_file_transfer_tunnel.reset();
|
||||
m_file_transfer_callbacks = {};
|
||||
}
|
||||
|
||||
void BBLPrinterAgent::set_cloud_agent(std::shared_ptr<ICloudServiceAgent> cloud)
|
||||
{
|
||||
m_cloud_agent = cloud;
|
||||
@@ -410,163 +20,6 @@ void BBLPrinterAgent::set_cloud_agent(std::shared_ptr<ICloudServiceAgent> cloud)
|
||||
// Communication
|
||||
// ============================================================================
|
||||
|
||||
std::string BBLPrinterAgent::ams_refresh_rfid_gcode(const std::string& tray_id)
|
||||
{
|
||||
return (boost::format("M620 R%1% \n") % tray_id).str();
|
||||
}
|
||||
|
||||
std::string BBLPrinterAgent::ams_calibrate_gcode(int ams_id)
|
||||
{
|
||||
return (boost::format("M620 C%1% \n") % ams_id).str();
|
||||
}
|
||||
|
||||
std::string BBLPrinterAgent::ams_select_tray_gcode(const std::string& tray_id)
|
||||
{
|
||||
return (boost::format("M620 P%1% \n") % tray_id).str();
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::command_ams_refresh_rfid(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode)
|
||||
{
|
||||
const std::string gcode = ams_refresh_rfid_gcode(tray_id);
|
||||
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode;
|
||||
nlohmann::json j;
|
||||
j["print"]["command"] = "gcode_line";
|
||||
j["print"]["param"] = gcode;
|
||||
j["print"]["sequence_id"] = std::to_string(sequence_id);
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::command_ams_calibrate(std::string dev_id, int ams_id, int sequence_id, bool lan_mode)
|
||||
{
|
||||
const std::string gcode = ams_calibrate_gcode(ams_id);
|
||||
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode;
|
||||
nlohmann::json j;
|
||||
j["print"]["command"] = "gcode_line";
|
||||
j["print"]["param"] = gcode;
|
||||
j["print"]["sequence_id"] = std::to_string(sequence_id);
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::command_ams_select_tray(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode)
|
||||
{
|
||||
const std::string gcode = ams_select_tray_gcode(tray_id);
|
||||
BOOST_LOG_TRIVIAL(trace) << "ams_debug: gcode_cmd" << gcode;
|
||||
nlohmann::json j;
|
||||
j["print"]["command"] = "gcode_line";
|
||||
j["print"]["param"] = gcode;
|
||||
j["print"]["sequence_id"] = std::to_string(sequence_id);
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::command_xyz_abs(std::string dev_id, int sequence_id, bool lan_mode)
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["print"]["command"] = "gcode_line";
|
||||
j["print"]["param"] = "G90 \n";
|
||||
j["print"]["sequence_id"] = std::to_string(sequence_id);
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::command_auto_leveling(std::string dev_id, int sequence_id, bool lan_mode)
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["print"]["command"] = "gcode_line";
|
||||
j["print"]["param"] = "G29 \n";
|
||||
j["print"]["sequence_id"] = std::to_string(sequence_id);
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::command_go_home(std::string dev_id, bool is_printing, bool supports_mqtt_homing, int sequence_id, bool lan_mode)
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["print"]["sequence_id"] = std::to_string(sequence_id);
|
||||
if (supports_mqtt_homing) {
|
||||
j["print"]["command"] = "back_to_center";
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
j["print"]["command"] = "gcode_line";
|
||||
j["print"]["param"] = is_printing ? "G28 X\n" : "G28 \n";
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::command_set_bed(std::string dev_id, int temp, bool supports_mqtt_bed_ctrl, int sequence_id, bool lan_mode)
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["print"]["sequence_id"] = std::to_string(sequence_id);
|
||||
if (supports_mqtt_bed_ctrl) {
|
||||
j["print"]["command"] = "set_bed_temp";
|
||||
j["print"]["temp"] = temp;
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
j["print"]["command"] = "gcode_line";
|
||||
j["print"]["param"] = (boost::format("M140 S%1%\n") % temp).str();
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::command_set_nozzle(std::string dev_id, int temp, int sequence_id, bool lan_mode)
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["print"]["command"] = "gcode_line";
|
||||
j["print"]["param"] = (boost::format("M104 S%1%\n") % temp).str();
|
||||
j["print"]["sequence_id"] = std::to_string(sequence_id);
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::command_axis_control(std::string dev_id, std::string axis, double unit, double input_val, int speed,
|
||||
bool is_core_xy, bool supports_mqtt_axis_control, int sequence_id, bool lan_mode)
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["print"]["sequence_id"] = std::to_string(sequence_id);
|
||||
|
||||
if (supports_mqtt_axis_control) {
|
||||
int dir = input_val > 0 ? 1 : -1;
|
||||
// i3-arch printers move the bed for Y/Z, so the on-screen direction is
|
||||
// reversed -- same negation the g-code fallback below applies.
|
||||
if (!is_core_xy && (axis == "Y" || axis == "Z")) {
|
||||
dir = -dir;
|
||||
}
|
||||
|
||||
j["print"]["command"] = "xyz_ctrl";
|
||||
j["print"]["axis"] = axis;
|
||||
j["print"]["dir"] = dir;
|
||||
j["print"]["mode"] = (std::abs(input_val) >= 10) ? 1 : 0;
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
double value = input_val;
|
||||
if (!is_core_xy && (axis == "Y" || axis == "Z")) {
|
||||
value = -1.0 * input_val;
|
||||
}
|
||||
|
||||
std::string value_str = (boost::format("%.1f") % (value * unit)).str();
|
||||
std::string gcode;
|
||||
if (axis == "X" || axis == "Y" || axis == "Z") {
|
||||
gcode = (boost::format("M211 S \nM211 X1 Y1 Z1\nM1002 push_ref_mode\nG91 \nG1 %1%%2% F%3%\nM1002 pop_ref_mode\nM211 R\n")
|
||||
% axis % value_str % speed).str();
|
||||
} else if (axis == "E") {
|
||||
gcode = (boost::format("M83 \nG0 %1%%2% F%3%\n") % axis % value_str % speed).str();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
j["print"]["command"] = "gcode_line";
|
||||
j["print"]["param"] = gcode;
|
||||
return publish(dev_id, j, lan_mode);
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::publish(const std::string& dev_id, const nlohmann::json& j, bool lan_mode)
|
||||
{
|
||||
const int rtn = lan_mode ? send_message_to_printer(dev_id, j.dump(), 0, 0) : send_message(dev_id, j.dump(), 0, 0);
|
||||
if (rtn == 0) {
|
||||
BOOST_LOG_TRIVIAL(info) << "publish_json: " << j.dump() << " code: " << rtn;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "publish_json: " << j.dump() << " code: " << rtn;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::send_message(std::string dev_id, std::string json_str, int qos, int flag)
|
||||
{
|
||||
auto& plugin = BBLNetworkPlugin::instance();
|
||||
@@ -633,89 +86,6 @@ int BBLPrinterAgent::send_message_to_printer(std::string dev_id, std::string jso
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string BBLPrinterAgent::get_local_camera_url(CameraURLParams params)
|
||||
{
|
||||
std::string url;
|
||||
if (params.protocol == LVL_Local)
|
||||
url = "bambu:///local/" + params.ip_address + ".?port=6000&user=" + params.user + "&passwd=" + params.password;
|
||||
else if (params.protocol == LVL_Rtsps)
|
||||
url = "bambu:///rtsps___" + params.user + ":" + params.password + "@" + params.ip_address + "/streaming/live/1?proto=rtsps";
|
||||
else if (params.protocol == LVL_Rtsp)
|
||||
url = "bambu:///rtsp___" + params.user + ":" + params.password + "@" + params.ip_address + "/streaming/live/1?proto=rtsp";
|
||||
else
|
||||
url = "bambu:///local/" + params.ip_address + ".?port=6000&user=" + params.user + "&passwd=" + params.password;
|
||||
|
||||
url += "&device=" + params.device;
|
||||
url += "&net_ver=" + params.network_version;
|
||||
url += "&dev_ver=" + params.device_version;
|
||||
url += "&cli_id=" + params.client_id;
|
||||
url += "&cli_ver=" + params.client_version;
|
||||
return url;
|
||||
}
|
||||
|
||||
std::string BBLPrinterAgent::get_local_file_transfer_url(const FileTransferURLParams& params)
|
||||
{
|
||||
// Keep the historical PartSkipDialog URL unchanged. It is a file-transfer
|
||||
// tunnel URL, not a camera URL, so it intentionally has no camera metadata
|
||||
// suffix and no dot before the query string.
|
||||
return "bambu:///local/" + params.ip_address + "?port=6000&user=" + params.username + "&passwd=" + params.password;
|
||||
}
|
||||
|
||||
bool BBLPrinterAgent::supports_remote_liveview(const std::string& printer_type) const
|
||||
{
|
||||
// The legacy Bambu networking plugin cannot provide remote live view for
|
||||
// the O-series printers. Keep this compatibility rule in the Bambu agent
|
||||
// instead of exposing plugin/version details to GUI code.
|
||||
return !(DevPrinterConfigUtil::get_printer_series_str(printer_type) == "series_o" &&
|
||||
BBLNetworkPlugin::instance().use_legacy_network());
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::get_file_transfer_url(std::string dev_id, std::function<void(FileTransferURLResult)> callback,
|
||||
FileTransferURLParams params)
|
||||
{
|
||||
if (params.url_state == URL_TCP) {
|
||||
FileTransferURLResult result;
|
||||
result.url = get_local_file_transfer_url(params);
|
||||
result.is_success = !result.url.empty();
|
||||
result.error_code = result.is_success ? 0 : -1;
|
||||
if (callback)
|
||||
callback(std::move(result));
|
||||
return result.is_success ? 0 : -1;
|
||||
}
|
||||
|
||||
if (!m_cloud_agent) {
|
||||
if (callback)
|
||||
callback({});
|
||||
return -1;
|
||||
}
|
||||
|
||||
const std::string protocols = "\"tutk\",\"agora\"";
|
||||
return m_cloud_agent->get_camera_url(
|
||||
std::move(dev_id) + "|" + params.device_version + "|" + protocols,
|
||||
[callback = std::move(callback)](CameraURLResult result) {
|
||||
if (!callback)
|
||||
return;
|
||||
FileTransferURLResult transfer_result;
|
||||
transfer_result.is_success = result.is_success;
|
||||
transfer_result.url = std::move(result.url);
|
||||
transfer_result.error_code = result.error_code;
|
||||
callback(std::move(transfer_result));
|
||||
},
|
||||
CameraURLParams{
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
LVL_None,
|
||||
params.device_id,
|
||||
params.network_version,
|
||||
params.device_version,
|
||||
params.refresh_url,
|
||||
params.client_id,
|
||||
params.client_version,
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Certificates
|
||||
// ============================================================================
|
||||
@@ -977,40 +347,14 @@ int BBLPrinterAgent::start_local_print_with_record(PrintParams params, OnUpdateS
|
||||
BBLNetworkPlugin::instance().get_start_local_print_with_record(), params, update_fn, cancel_fn, wait_fn);
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::verify_local_print_access(PrintParams params)
|
||||
{
|
||||
params.project_name = "verify_job";
|
||||
params.filename = Slic3r::resources_dir() + "/check_access_code.txt";
|
||||
params.try_emmc_print = false;
|
||||
|
||||
return start_send_gcode_to_sdcard(params, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::start_send_gcode_to_sdcard(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, OnWaitFn wait_fn)
|
||||
{
|
||||
int result = dispatch_start<func_start_send_gcode_to_sdcard_legacy, func_start_send_gcode_to_sdcard_0203>(
|
||||
return dispatch_start<func_start_send_gcode_to_sdcard_legacy, func_start_send_gcode_to_sdcard_0203>(
|
||||
BBLNetworkPlugin::instance().get_start_send_gcode_to_sdcard(), params, update_fn, cancel_fn, wait_fn);
|
||||
if (result != 0) {
|
||||
BOOST_LOG_TRIVIAL(error) << "start_send_gcode_to_sdcard failed: result=" << result
|
||||
<< ", try_emmc_print=" << params.try_emmc_print
|
||||
<< ", legacy_mode=" << BBLNetworkPlugin::instance().use_legacy_network()
|
||||
<< ", dev_ip=" << params.dev_ip << ", dev_id=" << params.dev_id;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int BBLPrinterAgent::start_local_print(PrintParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn)
|
||||
{
|
||||
if (params.connection_type == "lan" && params.print_type == "from_normal") {
|
||||
const int verify_result = verify_local_print_access(params);
|
||||
if (verify_result != 0) {
|
||||
BOOST_LOG_TRIVIAL(error) << "LAN connection verification failed: result=" << verify_result
|
||||
<< ", dev_ip=" << params.dev_ip << ", dev_id=" << params.dev_id
|
||||
<< ", password_length=" << params.password.size();
|
||||
return ORCA_NETWORK_ERR_ACCESS_VERIFICATION_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return dispatch_start<func_start_local_print_legacy, func_start_local_print_0203>(
|
||||
BBLNetworkPlugin::instance().get_start_local_print(), params, update_fn, cancel_fn);
|
||||
}
|
||||
|
||||
@@ -3,83 +3,11 @@
|
||||
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "ICloudServiceAgent.hpp"
|
||||
#include "FileTransferUtils.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
/**
|
||||
* BBLFileTransferTunnel - Bambu eMMC tunnel, backed by the Bambu network
|
||||
* plugin's ft_tunnel_* ABI (see FileTransferUtils.hpp). Only BBLPrinterAgent
|
||||
* constructs these; callers only ever see them through IFileTransferTunnel.
|
||||
*/
|
||||
class BBLFileTransferTunnel : public IFileTransferTunnel
|
||||
{
|
||||
public:
|
||||
BBLFileTransferTunnel(const std::string &url);
|
||||
~BBLFileTransferTunnel() override { reset(); }
|
||||
|
||||
void start_connect() override;
|
||||
bool sync_start_connect() override;
|
||||
void shutdown() override;
|
||||
bool check_valid() const override { return h_ != nullptr; }
|
||||
void *native() const noexcept override { return h_; }
|
||||
|
||||
private:
|
||||
void reset() noexcept
|
||||
{
|
||||
if (h_) {
|
||||
m_->ft_tunnel_release(h_);
|
||||
h_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
FileTransferModule *m_{};
|
||||
FT_TunnelHandle *h_{};
|
||||
};
|
||||
|
||||
/**
|
||||
* BBLFileTransferJob - a single ft_job_* operation (media-ability query,
|
||||
* file upload, ...) run on a BBLFileTransferTunnel. Same ABI-wrapper role
|
||||
* as BBLFileTransferTunnel; only BBLPrinterAgent constructs these.
|
||||
*/
|
||||
class BBLFileTransferJob : public IFileTransferJob
|
||||
{
|
||||
public:
|
||||
explicit BBLFileTransferJob(const std::string ¶ms_json);
|
||||
~BBLFileTransferJob() override { reset(); }
|
||||
|
||||
bool get_result(int &ec, int &resp_ec, std::string &json, std::vector<std::byte> &bin, uint32_t timeout_ms) override;
|
||||
void start_on(IFileTransferTunnel &t) override;
|
||||
// why: unlike on_result() (fires from a trampoline registered once in the ctor),
|
||||
// ft_job_set_msg_cb is only wired up here, lazily, on first real subscriber -
|
||||
// that ABI call has to happen in the concrete class, not the vendor-neutral base.
|
||||
void on_msg(MsgCb cb) override;
|
||||
bool try_get_msg(int &kind, std::string &json) override;
|
||||
bool get_msg(uint32_t timeout_ms, int &kind, std::string &json) override;
|
||||
void *native() const noexcept override { return h_; }
|
||||
bool check_valid() const override { return h_ != nullptr; }
|
||||
void cancel() override
|
||||
{
|
||||
if (m_->ft_job_cancel && h_) m_->ft_job_cancel(h_);
|
||||
}
|
||||
|
||||
private:
|
||||
void reset() noexcept
|
||||
{
|
||||
if (h_) {
|
||||
m_->ft_job_release(h_);
|
||||
h_ = nullptr;
|
||||
}
|
||||
}
|
||||
void solve_result(ft_job_result result);
|
||||
|
||||
FileTransferModule *m_{};
|
||||
FT_JobHandle *h_{};
|
||||
};
|
||||
|
||||
/**
|
||||
* BBLPrinterAgent - BBL DLL wrapper implementation of IPrinterAgent.
|
||||
*
|
||||
@@ -100,28 +28,9 @@ public:
|
||||
|
||||
// Communication
|
||||
int send_message(std::string dev_id, std::string json_str, int qos, int flag) override;
|
||||
static std::string ams_refresh_rfid_gcode(const std::string& tray_id);
|
||||
static std::string ams_calibrate_gcode(int ams_id);
|
||||
static std::string ams_select_tray_gcode(const std::string& tray_id);
|
||||
int command_ams_refresh_rfid(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode) override;
|
||||
int command_ams_calibrate(std::string dev_id, int ams_id, int sequence_id, bool lan_mode) override;
|
||||
int command_ams_select_tray(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode) override;
|
||||
int command_xyz_abs(std::string dev_id, int sequence_id, bool lan_mode) override;
|
||||
int command_auto_leveling(std::string dev_id, int sequence_id, bool lan_mode) override;
|
||||
int command_go_home(std::string dev_id, bool is_printing, bool supports_mqtt_homing, int sequence_id, bool lan_mode) override;
|
||||
int command_set_bed(std::string dev_id, int temp, bool supports_mqtt_bed_ctrl, int sequence_id, bool lan_mode) override;
|
||||
int command_set_nozzle(std::string dev_id, int temp, int sequence_id, bool lan_mode) override;
|
||||
int command_axis_control(std::string dev_id, std::string axis, double unit, double input_val, int speed,
|
||||
bool is_core_xy, bool supports_mqtt_axis_control, int sequence_id, bool lan_mode) 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;
|
||||
std::string get_local_camera_url(CameraURLParams params) override;
|
||||
std::string get_local_file_transfer_url(const FileTransferURLParams& params) override;
|
||||
bool supports_remote_liveview(const std::string& printer_type) const override;
|
||||
int get_file_transfer_url(std::string dev_id, std::function<void(FileTransferURLResult)> callback,
|
||||
FileTransferURLParams params) override;
|
||||
std::string default_lan_username() const override { return "bblp"; }
|
||||
|
||||
// Certificates
|
||||
int check_cert() override;
|
||||
@@ -175,30 +84,8 @@ public:
|
||||
int set_queue_on_main_fn(QueueOnMainFn fn) override;
|
||||
FilamentSyncMode get_filament_sync_mode() const override;
|
||||
|
||||
void prepare_file_transfer(const FileTransferRequest& request, FileTransferCallbacks cb) override;
|
||||
void get_file_destinations(FileTransferCallbacks cb) override;
|
||||
void upload_file(const std::string& path, const std::string& name, const std::string& destination,
|
||||
FileTransferCallbacks cb) override;
|
||||
void cancel_file_transfer() override;
|
||||
|
||||
|
||||
private:
|
||||
int verify_local_print_access(PrintParams params);
|
||||
|
||||
// why: the lan/cloud DECISION stays machine-side; keep this mechanical branch in sync with publish_json.
|
||||
int publish(const std::string& dev_id, const nlohmann::json& j, bool lan_mode);
|
||||
|
||||
std::shared_ptr<ICloudServiceAgent> m_cloud_agent;
|
||||
std::unique_ptr<IFileTransferTunnel> m_file_transfer_tunnel;
|
||||
std::unique_ptr<IFileTransferJob> m_file_transfer_job;
|
||||
FileTransferCallbacks m_file_transfer_callbacks;
|
||||
FileTransferRequest m_file_transfer_request;
|
||||
bool m_file_transfer_tcp{true};
|
||||
int m_file_transfer_try_count{0};
|
||||
uint64_t m_file_transfer_generation{0};
|
||||
|
||||
void start_file_transfer_attempt(uint64_t generation);
|
||||
void handle_file_transfer_connection(uint64_t generation, bool is_success, int error_code, std::string error_msg);
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#include <wx/wx.h>
|
||||
#include <type_traits>
|
||||
#include "FileTransferUtils.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/DeviceCore/DevManager.h"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@@ -33,4 +37,191 @@ FileTransferModule::FileTransferModule(ModuleHandle networking_module, int requi
|
||||
ft_job_get_msg = sym_lookup<fn_ft_job_get_msg>(networking_, "ft_job_get_msg");
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
FileTransferTunnel::FileTransferTunnel(FileTransferModule &m, const std::string &url) : m_(&m)
|
||||
{
|
||||
// Guard against missing symbols in older Bambu networking plugins.
|
||||
// These symbols were added in a newer plugin ABI; if the installed
|
||||
// plugin predates them, ft_tunnel_create/ft_tunnel_set_status_cb
|
||||
// will be null and calling them crashes.
|
||||
if (!m_->ft_tunnel_create || !m_->ft_tunnel_set_status_cb) {
|
||||
throw std::runtime_error("Bambu networking plugin is too old: missing ft_tunnel_* symbols. "
|
||||
"Please update the networking plugin.");
|
||||
}
|
||||
FT_TunnelHandle *h{};
|
||||
if (m_->ft_tunnel_create(url.c_str(), &h) != 0 || !h) {
|
||||
throw std::runtime_error("ft_tunnel_create failed");
|
||||
}
|
||||
h_ = h;
|
||||
|
||||
// C API: ft_status_cb(void* user, int old_status, int new_status, int err, const char* msg)
|
||||
auto tramp = [](void *user, int old_status, int new_status, int err_code, const char *msg) noexcept {
|
||||
auto *self = reinterpret_cast<FileTransferTunnel *>(user);
|
||||
self->status_ = new_status;
|
||||
if (!self->status_cb_) return;
|
||||
try {
|
||||
self->status_cb_(old_status, new_status, err_code, std::string(msg ? msg : ""));
|
||||
} catch (...) {}
|
||||
};
|
||||
if (m_->ft_tunnel_set_status_cb(h_, tramp, this) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_tunnel_set_status_cb failed"); }
|
||||
}
|
||||
|
||||
void FileTransferTunnel::start_connect()
|
||||
{
|
||||
// C API: ft_conn_cb(void* user, int ok, int err, const char* msg)
|
||||
auto tramp = [](void *user, int ok, int ec, const char *msg) noexcept {
|
||||
auto *pcb = reinterpret_cast<ConnectionCb *>(user);
|
||||
if (!pcb) return;
|
||||
try {
|
||||
(*pcb)(ok == 0, ec, std::string(msg ? msg : ""));
|
||||
} catch (...) {}
|
||||
};
|
||||
if (m_->ft_tunnel_start_connect(h_, tramp, &conn_cb_) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_tunnel_start_connect failed"); }
|
||||
}
|
||||
|
||||
bool FileTransferTunnel::sync_start_connect()
|
||||
{
|
||||
return m_->ft_tunnel_sync_connect(h_) == FT_OK;
|
||||
}
|
||||
|
||||
void FileTransferTunnel::on_connection(ConnectionCb cb) { conn_cb_ = std::move(cb); }
|
||||
void FileTransferTunnel::on_status(TunnelStatusCb cb) { status_cb_ = std::move(cb); }
|
||||
|
||||
void FileTransferTunnel::shutdown()
|
||||
{
|
||||
if (m_->ft_tunnel_shutdown) (void) m_->ft_tunnel_shutdown(h_);
|
||||
}
|
||||
|
||||
FileTransferJob::FileTransferJob(FileTransferModule &m, const std::string ¶ms_json) : m_(&m)
|
||||
{
|
||||
FT_JobHandle *h{};
|
||||
if (m_->ft_job_create(params_json.c_str(), &h) != 0 || !h) {
|
||||
|
||||
}
|
||||
h_ = h;
|
||||
|
||||
// C API: ft_job_result_cb(void* user, int tunnel_err, ft_job_result result)
|
||||
auto tramp = [](void *user, ft_job_result r) noexcept {
|
||||
auto *self = reinterpret_cast<FileTransferJob *>(user);
|
||||
if (!self) return;
|
||||
|
||||
try {
|
||||
self->finished_ = true;
|
||||
self->solve_result(r);
|
||||
|
||||
if (self->result_cb_) self->result_cb_(self->res_, self->resp_ec_, self->res_json_, self->res_bin_);
|
||||
self->m_->ft_job_result_destroy(&r);
|
||||
} catch (...) {
|
||||
// swallow
|
||||
}
|
||||
|
||||
try {
|
||||
if (auto *mod = self ? self->m_ : nullptr) {
|
||||
if (mod->ft_job_result_destroy)
|
||||
mod->ft_job_result_destroy(&r);
|
||||
else if (mod->ft_free) {
|
||||
if (r.json) mod->ft_free((void *) r.json);
|
||||
if (r.bin) mod->ft_free((void *) r.bin);
|
||||
}
|
||||
}
|
||||
} catch (...) {}
|
||||
};
|
||||
|
||||
if (m_->ft_job_set_result_cb(h_, tramp, this) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_job_set_result_cb failed"); }
|
||||
}
|
||||
|
||||
void FileTransferJob::on_result(ResultCb cb) { result_cb_ = std::move(cb); }
|
||||
|
||||
bool FileTransferJob::get_result(int &ec, int &resp_ec, std::string &json, std::vector<std::byte> &bin, uint32_t timeout_ms)
|
||||
{
|
||||
if (!h_) throw std::runtime_error("job handle invalid");
|
||||
ft_job_result result;
|
||||
if (m_->ft_job_get_result(h_, timeout_ms, &result) == ft_err::FT_EXCEPTION) return false;
|
||||
solve_result(result);
|
||||
m_->ft_job_result_destroy(&result);
|
||||
ec = res_;
|
||||
resp_ec = res_;
|
||||
json = res_json_;
|
||||
bin = res_bin_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileTransferJob::start_on(FileTransferTunnel &t)
|
||||
{
|
||||
if (!h_) throw std::runtime_error("job handle invalid");
|
||||
if (m_->ft_tunnel_start_job(t.native(), h_) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_tunnel_start_job failed"); }
|
||||
}
|
||||
|
||||
void FileTransferJob::on_msg(MsgCb cb)
|
||||
{
|
||||
msg_cb_ = std::move(cb);
|
||||
if (!h_) return;
|
||||
|
||||
// C API: ft_job_msg_cb(void* user, ft_job_msg msg)
|
||||
auto tramp = [](void *user, ft_job_msg m) noexcept {
|
||||
auto *self = reinterpret_cast<FileTransferJob *>(user);
|
||||
if (!self) return;
|
||||
try {
|
||||
if (self->msg_cb_) { self->msg_cb_(m.kind, std::string(m.json ? m.json : "")); }
|
||||
} catch (...) {}
|
||||
|
||||
try {
|
||||
if (auto *mod = self->m_) {
|
||||
if (mod->ft_job_msg_destroy)
|
||||
mod->ft_job_msg_destroy(&m);
|
||||
else if (mod->ft_free && m.json)
|
||||
mod->ft_free((void *) m.json);
|
||||
}
|
||||
} catch (...) {}
|
||||
};
|
||||
|
||||
if (m_->ft_job_set_msg_cb(h_, tramp, this) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_job_set_msg_cb failed"); }
|
||||
}
|
||||
|
||||
bool FileTransferJob::try_get_msg(int &kind, std::string &json)
|
||||
{
|
||||
if (!h_) return false;
|
||||
ft_job_msg m{};
|
||||
int rc = m_->ft_job_try_get_msg(h_, &m);
|
||||
if (rc != 0) return false;
|
||||
|
||||
kind = m.kind;
|
||||
json.assign(m.json ? m.json : "");
|
||||
|
||||
if (m_->ft_job_msg_destroy)
|
||||
m_->ft_job_msg_destroy(&m);
|
||||
else if (m_->ft_free && m.json)
|
||||
m_->ft_free((void *) m.json);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileTransferJob::get_msg(uint32_t timeout_ms, int &kind, std::string &json)
|
||||
{
|
||||
if (!h_) return false;
|
||||
ft_job_msg m{};
|
||||
int rc = m_->ft_job_get_msg(h_, timeout_ms, &m);
|
||||
if (rc != 0) return false;
|
||||
|
||||
kind = m.kind;
|
||||
json.assign(m.json ? m.json : "");
|
||||
|
||||
if (m_->ft_job_msg_destroy)
|
||||
m_->ft_job_msg_destroy(&m);
|
||||
else if (m_->ft_free && m.json)
|
||||
m_->ft_free((void *) m.json);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileTransferJob::solve_result(ft_job_result result)
|
||||
{
|
||||
res_ = result.ec;
|
||||
resp_ec_ = result.resp_ec;
|
||||
|
||||
res_bin_.clear();
|
||||
if (result.bin && result.bin_size) res_bin_.assign(reinterpret_cast<const std::byte *>(result.bin),
|
||||
reinterpret_cast<const std::byte *>(result.bin) + result.bin_size);
|
||||
res_json_.assign(result.json ? result.json : "");
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
@@ -1,7 +1,13 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -128,11 +134,103 @@ struct FileTransferModule
|
||||
FileTransferModule &operator=(const FileTransferModule &) = delete;
|
||||
};
|
||||
|
||||
// FileTransferTunnel/FileTransferJob (the OOP wrapper around the ft_tunnel_*/
|
||||
// ft_job_* ABI below) live in BBLPrinterAgent.hpp as BBLFileTransferTunnel/
|
||||
// BBLFileTransferJob, implementing IFileTransferTunnel/IFileTransferJob
|
||||
// (IPrinterAgent.hpp) - this header stays the low-level symbol-table layer
|
||||
// only, same role as bambu_networking.hpp's function pointer typedefs.
|
||||
class FileTransferTunnel
|
||||
{
|
||||
public:
|
||||
using ConnectionCb = std::function<void(bool is_success, int err_code, std::string error_msg)>;
|
||||
using TunnelStatusCb = std::function<void(int old_status, int new_status, int err_code, std::string error_msg)>;
|
||||
|
||||
explicit FileTransferTunnel(FileTransferModule &m, const std::string &url);
|
||||
~FileTransferTunnel() { reset(); }
|
||||
|
||||
FileTransferTunnel(const FileTransferTunnel &) = delete;
|
||||
FileTransferTunnel &operator=(const FileTransferTunnel &) = delete;
|
||||
FileTransferTunnel(FileTransferTunnel &&) = delete;
|
||||
FileTransferTunnel &operator=(FileTransferTunnel &&) = delete;
|
||||
|
||||
void start_connect();
|
||||
bool sync_start_connect();
|
||||
void on_connection(ConnectionCb cb);
|
||||
void on_status(TunnelStatusCb cb);
|
||||
|
||||
void shutdown();
|
||||
|
||||
int get_status() const { return status_; }
|
||||
bool check_valid() const { return h_ != nullptr; }
|
||||
FT_TunnelHandle *native() const noexcept { return h_; }
|
||||
|
||||
private:
|
||||
void reset() noexcept
|
||||
{
|
||||
if (h_) {
|
||||
m_->ft_tunnel_release(h_);
|
||||
h_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int status_{};
|
||||
FileTransferModule *m_{};
|
||||
FT_TunnelHandle *h_{};
|
||||
ConnectionCb conn_cb_{};
|
||||
TunnelStatusCb status_cb_{};
|
||||
};
|
||||
|
||||
class FileTransferJob
|
||||
{
|
||||
public:
|
||||
using ResultCb = std::function<void(int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res)>;
|
||||
using MsgCb = std::function<void(int kind, std::string json)>;
|
||||
|
||||
explicit FileTransferJob(FileTransferModule &m, const std::string ¶ms_json);
|
||||
~FileTransferJob() { reset(); }
|
||||
|
||||
FileTransferJob(const FileTransferJob &) = delete;
|
||||
FileTransferJob &operator=(const FileTransferJob &) = delete;
|
||||
FileTransferJob(FileTransferJob &&) = delete;
|
||||
FileTransferJob &operator=(FileTransferJob &&) = delete;
|
||||
|
||||
void on_result(ResultCb cb);
|
||||
|
||||
bool get_result(int &ec, int &resp_ec, std::string &json, std::vector<std::byte> &bin, uint32_t timeout_ms);
|
||||
|
||||
void start_on(FileTransferTunnel &t);
|
||||
|
||||
void on_msg(MsgCb cb);
|
||||
|
||||
bool try_get_msg(int &kind, std::string &json);
|
||||
|
||||
bool get_msg(uint32_t timeout_ms, int &kind, std::string &json);
|
||||
|
||||
FT_JobHandle *native() const noexcept { return h_; }
|
||||
bool check_valid() const { return h_ != nullptr; }
|
||||
bool finished() const { return finished_; }
|
||||
|
||||
void cancel()
|
||||
{
|
||||
if (m_->ft_job_cancel && h_) m_->ft_job_cancel(h_);
|
||||
}
|
||||
|
||||
private:
|
||||
void reset() noexcept
|
||||
{
|
||||
if (h_) {
|
||||
m_->ft_job_release(h_);
|
||||
h_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void solve_result(ft_job_result result);
|
||||
|
||||
FileTransferModule *m_{};
|
||||
FT_JobHandle *h_{};
|
||||
ResultCb result_cb_{};
|
||||
MsgCb msg_cb_{};
|
||||
bool finished_ = false;
|
||||
int res_ = 0;
|
||||
int resp_ec_ = 0;
|
||||
std::string res_json_;
|
||||
std::vector<std::byte> res_bin_;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
inline FileTransferModule *g_mod = nullptr;
|
||||
|
||||
@@ -47,9 +47,6 @@ struct CloudEvent {
|
||||
using AppOnServerConnectedFn = std::function<void(CloudEvent event, int return_code, int reason_code)>;
|
||||
using AppOnHttpErrorFn = std::function<void(CloudEvent event, unsigned http_code, std::string http_body)>;
|
||||
|
||||
struct CameraURLParams;
|
||||
struct CameraURLResult;
|
||||
|
||||
class ICloudServiceAgent {
|
||||
public:
|
||||
virtual ~ICloudServiceAgent() = default;
|
||||
@@ -331,8 +328,7 @@ public:
|
||||
/**
|
||||
* Request live camera streaming URL.
|
||||
*/
|
||||
virtual int get_camera_url(std::string dev_id, std::function<void(CameraURLResult)> callback,
|
||||
CameraURLParams params) = 0;
|
||||
virtual int get_camera_url(std::string dev_id, std::function<void(std::string)> callback) = 0;
|
||||
|
||||
/**
|
||||
* Fetch staff-picked designs from model mall.
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define __I_PRINTER_AGENT_HPP__
|
||||
|
||||
#include "bambu_networking.hpp"
|
||||
#include <slic3r/GUI/DeviceManager.hpp>
|
||||
// why: these extend the BAMBU_NETWORK_* return space rather than opening a new one - the value
|
||||
// flows through the same int domain callers already compare against BAMBU_NETWORK_SUCCESS.
|
||||
// They live here and not in bambu_networking.hpp because that file is a vendor header replaced
|
||||
@@ -10,14 +9,8 @@
|
||||
// -70xx is free: the vendor occupies -1..-25 and -10xx through -60xx.
|
||||
#define ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED -7010 // no translation exists for this command
|
||||
#define ORCA_NETWORK_ERR_CAP_NOT_AVAILABLE -7020 // a translation exists; this printer lacks the capability
|
||||
#define ORCA_NETWORK_ERR_ACCESS_VERIFICATION_FAILED -7030 // printer access preflight failed before printing
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
|
||||
#include "NetworkAgent.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@@ -50,77 +43,6 @@ enum class FilamentSyncMode {
|
||||
pull ///< On-demand fetch via REST API (blocking call)
|
||||
};
|
||||
|
||||
class IFileTransferTunnel
|
||||
{
|
||||
public:
|
||||
using ConnectionCb = std::function<void(bool is_success, int err_code, std::string error_msg)>;
|
||||
using TunnelStatusCb = std::function<void(int old_status, int new_status, int err_code, std::string error_msg)>;
|
||||
|
||||
explicit IFileTransferTunnel(const std::string& url) : url_(url) {}
|
||||
virtual ~IFileTransferTunnel() = default;
|
||||
|
||||
IFileTransferTunnel(const IFileTransferTunnel&) = delete;
|
||||
IFileTransferTunnel& operator=(const IFileTransferTunnel&) = delete;
|
||||
IFileTransferTunnel(IFileTransferTunnel&&) = delete;
|
||||
IFileTransferTunnel& operator=(IFileTransferTunnel&&) = delete;
|
||||
|
||||
virtual void start_connect() = 0;
|
||||
virtual bool sync_start_connect() = 0;
|
||||
virtual void on_connection(ConnectionCb cb) { conn_cb_ = std::move(cb); }
|
||||
virtual void on_status(TunnelStatusCb cb) { status_cb_ = std::move(cb); }
|
||||
|
||||
virtual void shutdown() = 0;
|
||||
|
||||
virtual int get_status() const { return status_; }
|
||||
virtual bool check_valid() const = 0;
|
||||
|
||||
// why: IFileTransferJob::start_on() only ever sees a tunnel through this interface,
|
||||
// but needs the concrete backend handle to hand to its own start-job call - native()
|
||||
// is the type-erased escape hatch, same pattern IFileTransferJob::native() already uses.
|
||||
virtual void *native() const noexcept { return nullptr; }
|
||||
|
||||
protected:
|
||||
std::string url_;
|
||||
int status_{};
|
||||
ConnectionCb conn_cb_{};
|
||||
TunnelStatusCb status_cb_{};
|
||||
};
|
||||
|
||||
class IFileTransferJob {
|
||||
public:
|
||||
using ResultCb = std::function<void(int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res)>;
|
||||
using MsgCb = std::function<void(int kind, std::string json)>;
|
||||
|
||||
explicit IFileTransferJob(const std::string ¶ms_json) : params_json_(params_json) {}
|
||||
virtual ~IFileTransferJob() = default;
|
||||
|
||||
IFileTransferJob(const IFileTransferJob &) = delete;
|
||||
IFileTransferJob &operator=(const IFileTransferJob &) = delete;
|
||||
IFileTransferJob(IFileTransferJob &&) = delete;
|
||||
IFileTransferJob &operator=(IFileTransferJob &&) = delete;
|
||||
|
||||
virtual void on_result(ResultCb cb) { result_cb_ = std::move(cb); }
|
||||
virtual bool get_result(int &ec, int &resp_ec, std::string &json, std::vector<std::byte> &bin, uint32_t timeout_ms) = 0;
|
||||
virtual void start_on(IFileTransferTunnel &t) = 0;
|
||||
virtual void on_msg(MsgCb cb) { msg_cb_ = std::move(cb); }
|
||||
virtual bool try_get_msg(int &kind, std::string &json) = 0;
|
||||
virtual bool get_msg(uint32_t timeout_ms, int &kind, std::string &json) = 0;
|
||||
virtual void *native() const noexcept { return nullptr; }
|
||||
virtual bool check_valid() const = 0;
|
||||
virtual bool finished() const { return finished_; }
|
||||
virtual void cancel() = 0;
|
||||
|
||||
protected:
|
||||
std::string params_json_;
|
||||
ResultCb result_cb_{};
|
||||
MsgCb msg_cb_{};
|
||||
bool finished_ = false;
|
||||
int res_ = 0;
|
||||
int resp_ec_ = 0;
|
||||
std::string res_json_;
|
||||
std::vector<std::byte> res_bin_;
|
||||
};
|
||||
|
||||
/**
|
||||
* IPrinterAgent - Interface for printer operations.
|
||||
*
|
||||
@@ -162,62 +84,6 @@ public:
|
||||
*/
|
||||
virtual int send_message(std::string dev_id, std::string json_str, int qos, int flag) = 0;
|
||||
|
||||
// why: gcode is firmware dialect, not a waist concept - commands whose body is Bambu-dialect
|
||||
// gcode live on the agent that speaks it; the default is an honest refusal that MachineObject's
|
||||
// publish funnel turns into a dialog.
|
||||
virtual int command_ams_refresh_rfid(std::string, std::string, int, bool)
|
||||
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; }
|
||||
virtual int command_ams_calibrate(std::string, int, int, bool)
|
||||
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; }
|
||||
virtual int command_ams_select_tray(std::string, std::string, int, bool)
|
||||
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; }
|
||||
virtual int command_xyz_abs(std::string dev_id, int sequence_id, bool lan_mode)
|
||||
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; }
|
||||
virtual int command_auto_leveling(std::string dev_id, int sequence_id, bool lan_mode)
|
||||
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; }
|
||||
virtual int command_go_home(std::string dev_id, bool is_printing, bool supports_mqtt_homing, int sequence_id, bool lan_mode)
|
||||
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; }
|
||||
virtual int command_set_bed(std::string dev_id, int temp, bool supports_mqtt_bed_ctrl, int sequence_id, bool lan_mode)
|
||||
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; }
|
||||
virtual int command_set_nozzle(std::string dev_id, int temp, int sequence_id, bool lan_mode)
|
||||
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; }
|
||||
virtual int command_axis_control(std::string dev_id, std::string axis, double unit, double input_val, int speed,
|
||||
bool is_core_xy, bool supports_mqtt_axis_control, int sequence_id, bool lan_mode)
|
||||
{ return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED; }
|
||||
|
||||
/**
|
||||
* Build a ready-to-use local (LAN) camera stream URL for this agent's protocol.
|
||||
* Returns an empty string if the agent has no local camera stream support.
|
||||
*/
|
||||
virtual std::string get_local_camera_url(CameraURLParams params) { return ""; }
|
||||
|
||||
/**
|
||||
* Build a ready-to-use local (LAN) file transfer URL for this agent's protocol.
|
||||
* Returns an empty string if the agent has no local file transfer support.
|
||||
*/
|
||||
virtual std::string get_local_file_transfer_url(const FileTransferURLParams& params) { return ""; }
|
||||
|
||||
/**
|
||||
* Whether remote live view is available for the selected printer and agent
|
||||
* protocol. Implementations may use their plugin/version compatibility
|
||||
* rules; the neutral default keeps existing agents permissive.
|
||||
*/
|
||||
virtual bool supports_remote_liveview(const std::string& printer_type) const
|
||||
{ (void) printer_type; return true; }
|
||||
|
||||
virtual int get_file_transfer_url(std::string, std::function<void(FileTransferURLResult)> callback, FileTransferURLParams)
|
||||
{
|
||||
if (callback)
|
||||
callback({});
|
||||
return ORCA_NETWORK_ERR_CMD_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default LAN account username for this agent's protocol, if it has a fixed one.
|
||||
* Returns an empty string if the agent has no fixed default (e.g. caller must supply one).
|
||||
*/
|
||||
virtual std::string default_lan_username() const { return {}; }
|
||||
|
||||
/**
|
||||
* Establish a direct LAN connection to a printer.
|
||||
*/
|
||||
@@ -424,56 +290,6 @@ public:
|
||||
* Populates the MachineObject's DevFilaSystem with fetched filament data.
|
||||
*/
|
||||
virtual bool fetch_filament_info(std::string dev_id) { return false; }
|
||||
|
||||
struct FileTransferRequest
|
||||
{
|
||||
std::string device_id;
|
||||
std::string device_ip;
|
||||
std::string access_code;
|
||||
std::string network_version;
|
||||
std::string device_version;
|
||||
std::string refresh_url;
|
||||
std::string client_id;
|
||||
std::string client_version;
|
||||
bool lan_mode{false};
|
||||
};
|
||||
|
||||
struct FileTransferCallbacks
|
||||
{
|
||||
std::function<void(bool is_success, int error_code, std::string error_msg)> on_connection;
|
||||
std::function<void(int result, int response_error, std::string json_result)> on_destinations;
|
||||
std::function<void(int progress)> on_progress;
|
||||
std::function<void(int result, int response_error, std::string json_result, std::vector<std::byte> binary_result)> on_result;
|
||||
std::function<void()> file_transfer_error;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepare the agent's file-transfer session. The transport is agent-owned;
|
||||
* callers must not need to know whether it is a tunnel, HTTP connection,
|
||||
* or another protocol.
|
||||
*/
|
||||
virtual void prepare_file_transfer(const FileTransferRequest&, FileTransferCallbacks cb)
|
||||
{
|
||||
if (cb.file_transfer_error)
|
||||
cb.file_transfer_error();
|
||||
}
|
||||
|
||||
/** Query the destinations available for the prepared transfer session. */
|
||||
virtual void get_file_destinations(FileTransferCallbacks cb)
|
||||
{
|
||||
if (cb.file_transfer_error)
|
||||
cb.file_transfer_error();
|
||||
}
|
||||
|
||||
/** Upload a file using the prepared transfer session. */
|
||||
virtual void upload_file(const std::string&, const std::string&, const std::string&, FileTransferCallbacks cb)
|
||||
{
|
||||
if (cb.file_transfer_error)
|
||||
cb.file_transfer_error();
|
||||
}
|
||||
|
||||
/** Cancel the current file-transfer operation and release its resources. */
|
||||
virtual void cancel_file_transfer() {}
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "NetworkAgent.hpp"
|
||||
#include "BBLNetworkPlugin.hpp"
|
||||
@@ -508,12 +507,11 @@ int NetworkAgent::modify_printer_name(std::string dev_id, std::string dev_name,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetworkAgent::get_camera_url(std::string dev_id, std::function<void(CameraURLResult)> callback,
|
||||
const std::string& provider, CameraURLParams params)
|
||||
int NetworkAgent::get_camera_url(std::string dev_id, std::function<void(std::string)> callback, const std::string& provider)
|
||||
{
|
||||
const auto cloud_agent = get_cloud_agent(provider);
|
||||
if (cloud_agent)
|
||||
return cloud_agent->get_camera_url(std::move(dev_id), std::move(callback), std::move(params));
|
||||
return cloud_agent->get_camera_url(std::move(dev_id), std::move(callback));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -769,70 +767,6 @@ int NetworkAgent::send_message(std::string dev_id, std::string json_str, int qos
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetworkAgent::command_ams_refresh_rfid(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->command_ams_refresh_rfid(dev_id, tray_id, sequence_id, lan_mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetworkAgent::command_ams_calibrate(std::string dev_id, int ams_id, int sequence_id, bool lan_mode)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->command_ams_calibrate(dev_id, ams_id, sequence_id, lan_mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetworkAgent::command_ams_select_tray(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->command_ams_select_tray(dev_id, tray_id, sequence_id, lan_mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetworkAgent::command_xyz_abs(std::string dev_id, int sequence_id, bool lan_mode)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->command_xyz_abs(dev_id, sequence_id, lan_mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetworkAgent::command_auto_leveling(std::string dev_id, int sequence_id, bool lan_mode)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->command_auto_leveling(dev_id, sequence_id, lan_mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetworkAgent::command_go_home(std::string dev_id, bool is_printing, bool supports_mqtt_homing, int sequence_id, bool lan_mode)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->command_go_home(dev_id, is_printing, supports_mqtt_homing, sequence_id, lan_mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetworkAgent::command_set_bed(std::string dev_id, int temp, bool supports_mqtt_bed_ctrl, int sequence_id, bool lan_mode)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->command_set_bed(dev_id, temp, supports_mqtt_bed_ctrl, sequence_id, lan_mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetworkAgent::command_set_nozzle(std::string dev_id, int temp, int sequence_id, bool lan_mode)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->command_set_nozzle(dev_id, temp, sequence_id, lan_mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetworkAgent::command_axis_control(std::string dev_id, std::string axis, double unit, double input_val, int speed,
|
||||
bool is_core_xy, bool supports_mqtt_axis_control, int sequence_id, bool lan_mode)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->command_axis_control(dev_id, axis, unit, input_val, speed, is_core_xy, supports_mqtt_axis_control, sequence_id, lan_mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int NetworkAgent::connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
@@ -854,45 +788,6 @@ int NetworkAgent::send_message_to_printer(std::string dev_id, std::string json_s
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string NetworkAgent::get_local_camera_url(CameraURLParams params)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->get_local_camera_url(params);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string NetworkAgent::get_local_file_transfer_url(const FileTransferURLParams& params)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->get_local_file_transfer_url(params);
|
||||
return {};
|
||||
}
|
||||
|
||||
bool NetworkAgent::supports_remote_liveview(const std::string& printer_type) const
|
||||
{
|
||||
// Preserve the historical permissive behavior while the printer agent is
|
||||
// being selected. A missing agent must not turn a supported remote
|
||||
// protocol into LVNone before the Bambu agent has been installed.
|
||||
return !m_printer_agent || m_printer_agent->supports_remote_liveview(printer_type);
|
||||
}
|
||||
|
||||
int NetworkAgent::get_file_transfer_url(std::string dev_id, std::function<void(FileTransferURLResult)> callback,
|
||||
FileTransferURLParams params)
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->get_file_transfer_url(std::move(dev_id), std::move(callback), std::move(params));
|
||||
if (callback)
|
||||
callback({});
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string NetworkAgent::default_lan_username() const
|
||||
{
|
||||
if (m_printer_agent)
|
||||
return m_printer_agent->default_lan_username();
|
||||
return {};
|
||||
}
|
||||
|
||||
int NetworkAgent::check_cert()
|
||||
{
|
||||
if (m_printer_agent)
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
#define __NETWORK_Agent_HPP__
|
||||
|
||||
#include "bambu_networking.hpp"
|
||||
|
||||
#include "libslic3r/ProjectTask.hpp"
|
||||
#include "ICloudServiceAgent.hpp"
|
||||
#include "slic3r/GUI/DeviceManager.hpp"
|
||||
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -14,53 +12,6 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class IPrinterAgent;
|
||||
enum class FilamentSyncMode;
|
||||
|
||||
enum URL_STATE {
|
||||
URL_TCP,
|
||||
URL_TUTK,
|
||||
};
|
||||
|
||||
struct CameraURLParams {
|
||||
std::string ip_address;
|
||||
std::string user;
|
||||
std::string password;
|
||||
LiveviewLocal protocol;
|
||||
std::string device;
|
||||
std::string network_version;
|
||||
std::string device_version;
|
||||
std::string refresh_url;
|
||||
std::string client_id;
|
||||
std::string client_version;
|
||||
bool apply_meta{false};
|
||||
};
|
||||
|
||||
struct FileTransferURLParams {
|
||||
URL_STATE url_state{URL_TCP};
|
||||
std::string ip_address;
|
||||
std::string username;
|
||||
std::string password;
|
||||
std::string device_id;
|
||||
std::string network_version;
|
||||
std::string device_version;
|
||||
std::string refresh_url;
|
||||
std::string client_id;
|
||||
std::string client_version;
|
||||
};
|
||||
|
||||
struct FileTransferURLResult {
|
||||
bool is_success{false};
|
||||
std::string url;
|
||||
int error_code{-1};
|
||||
};
|
||||
|
||||
struct CameraURLResult {
|
||||
bool is_success{false};
|
||||
std::string url;
|
||||
int error_code{-1};
|
||||
};
|
||||
|
||||
// Forward declaration
|
||||
class BBLNetworkPlugin;
|
||||
|
||||
@@ -157,8 +108,7 @@ public:
|
||||
int get_slice_info(std::string project_id, std::string profile_id, int plate_index, std::string* slice_json, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
int query_bind_status(std::vector<std::string> query_list, unsigned int* http_code, std::string* http_body, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
int modify_printer_name(std::string dev_id, std::string dev_name, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
int get_camera_url(std::string dev_id, std::function<void(CameraURLResult)> callback,
|
||||
const std::string& provider = ORCA_CLOUD_PROVIDER, CameraURLParams params = {});
|
||||
int get_camera_url(std::string dev_id, std::function<void(std::string)> callback, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
int get_design_staffpick(int offset, int limit, std::function<void(std::string)> callback, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
int start_publish(PublishParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, std::string* out, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
int get_model_publish_url(std::string* url, const std::string& provider = ORCA_CLOUD_PROVIDER);
|
||||
@@ -192,25 +142,9 @@ public:
|
||||
int set_on_local_message_fn(OnMessageFn fn);
|
||||
int set_server_callback(OnServerErrFn fn);
|
||||
int send_message(std::string dev_id, std::string json_str, int qos, int flag);
|
||||
int command_ams_refresh_rfid(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode);
|
||||
int command_ams_calibrate(std::string dev_id, int ams_id, int sequence_id, bool lan_mode);
|
||||
int command_ams_select_tray(std::string dev_id, std::string tray_id, int sequence_id, bool lan_mode);
|
||||
int command_xyz_abs(std::string dev_id, int sequence_id, bool lan_mode);
|
||||
int command_auto_leveling(std::string dev_id, int sequence_id, bool lan_mode);
|
||||
int command_go_home(std::string dev_id, bool is_printing, bool supports_mqtt_homing, int sequence_id, bool lan_mode);
|
||||
int command_set_bed(std::string dev_id, int temp, bool supports_mqtt_bed_ctrl, int sequence_id, bool lan_mode);
|
||||
int command_set_nozzle(std::string dev_id, int temp, int sequence_id, bool lan_mode);
|
||||
int command_axis_control(std::string dev_id, std::string axis, double unit, double input_val, int speed,
|
||||
bool is_core_xy, bool supports_mqtt_axis_control, int sequence_id, bool lan_mode);
|
||||
int connect_printer(std::string dev_id, std::string dev_ip, std::string username, std::string password, bool use_ssl);
|
||||
int disconnect_printer();
|
||||
int send_message_to_printer(std::string dev_id, std::string json_str, int qos, int flag);
|
||||
std::string get_local_camera_url(CameraURLParams params);
|
||||
std::string get_local_file_transfer_url(const FileTransferURLParams& params);
|
||||
bool supports_remote_liveview(const std::string& printer_type) const;
|
||||
int get_file_transfer_url(std::string dev_id, std::function<void(FileTransferURLResult)> callback,
|
||||
FileTransferURLParams params = {});
|
||||
std::string default_lan_username() const;
|
||||
int check_cert();
|
||||
void install_device_cert(std::string dev_id, bool lan_only);
|
||||
bool start_discovery(bool start, bool sending);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "OrcaCloudServiceAgent.hpp"
|
||||
#include "NetworkAgent.hpp"
|
||||
#include "Http.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
@@ -2699,12 +2698,11 @@ int OrcaCloudServiceAgent::modify_printer_name(std::string dev_id, std::string d
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
int OrcaCloudServiceAgent::get_camera_url(std::string dev_id, std::function<void(CameraURLResult)> callback, CameraURLParams params)
|
||||
int OrcaCloudServiceAgent::get_camera_url(std::string dev_id, std::function<void(std::string)> callback)
|
||||
{
|
||||
(void) params;
|
||||
BOOST_LOG_TRIVIAL(debug) << "OrcaCloudServiceAgent: get_camera_url (stub)";
|
||||
if (callback)
|
||||
callback({});
|
||||
callback("");
|
||||
return BAMBU_NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ public:
|
||||
// ========================================================================
|
||||
// ICloudServiceAgent Interface Implementation - Model Mall & Publishing
|
||||
// ========================================================================
|
||||
int get_camera_url(std::string dev_id, std::function<void(CameraURLResult)> callback, CameraURLParams params) override;
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user