mirror of
https://git.mirrors.martin98.com/https://github.com/SoftFever/OrcaSlicer.git
synced 2025-06-04 11:25:39 +08:00

* "non zero" -> "non-zero" * "Z hop" -> "Z-hop" * "works" -> "is working" * "version at least x" -> "version x or higher" * "printing job" -> "print job" "to print on" -> "printing on" * "is not find" -> "was not found" * "boundary of plate" -> "plate boundaries" * "toolchange" -> "tool change" * "colour" -> "color" * "cancelled" -> "canceled" * "can not" -> "cannot" * "gcode" -> "G-code"
383 lines
15 KiB
C++
383 lines
15 KiB
C++
#include "SendJob.hpp"
|
|
#include "libslic3r/MTUtils.hpp"
|
|
#include "libslic3r/Model.hpp"
|
|
#include "libslic3r/PresetBundle.hpp"
|
|
#include "slic3r/GUI/Plater.hpp"
|
|
#include "slic3r/GUI/GUI.hpp"
|
|
#include "slic3r/GUI/GUI_App.hpp"
|
|
#include "slic3r/GUI/format.hpp"
|
|
|
|
namespace Slic3r {
|
|
namespace GUI {
|
|
|
|
static auto check_gcode_failed_str = _u8L("Abnormal print file data. Please slice again.");
|
|
static auto printjob_cancel_str = _u8L("Task canceled.");
|
|
static auto timeout_to_upload_str = _u8L("Upload task timed out. Please check the network status and try again.");
|
|
static auto failed_in_cloud_service_str = _u8L("Cloud service connection failed. Please try again.");
|
|
static auto file_is_not_exists_str = _u8L("Print file not found. please slice again.");
|
|
static auto file_over_size_str = _u8L("The print file exceeds the maximum allowable size (1GB). Please simplify the model and slice again.");
|
|
static auto print_canceled_str = _u8L("Task canceled.");
|
|
static auto send_print_failed_str = _u8L("Failed to send the print job. Please try again.");
|
|
static auto upload_ftp_failed_str = _u8L("Failed to upload file to ftp. Please try again.");
|
|
|
|
static auto desc_network_error = _u8L("Check the current status of the bambu server by clicking on the link above.");
|
|
static auto desc_file_too_large = _u8L("The size of the print file is too large. Please adjust the file size and try again.");
|
|
static auto desc_fail_not_exist = _u8L("Print file not found, Please slice it again and send it for printing.");
|
|
static auto desc_upload_ftp_failed = _u8L("Failed to upload print file to FTP. Please check the network status and try again.");
|
|
|
|
static auto sending_over_lan_str = _u8L("Sending print job over LAN");
|
|
static auto sending_over_cloud_str = _u8L("Sending print job through cloud service");
|
|
|
|
SendJob::SendJob(std::string dev_id)
|
|
: m_plater{wxGetApp().plater()},
|
|
m_dev_id(dev_id)
|
|
{
|
|
m_print_job_completed_id = m_plater->get_send_finished_event();
|
|
}
|
|
|
|
void SendJob::prepare()
|
|
{
|
|
m_plater->get_print_job_data(&job_data);
|
|
std::string temp_file = Slic3r::resources_dir() + "/check_access_code.txt";
|
|
auto check_access_code_path = temp_file.c_str();
|
|
BOOST_LOG_TRIVIAL(trace) << "sned_job: check_access_code_path = " << check_access_code_path;
|
|
job_data._temp_path = fs::path(check_access_code_path);
|
|
}
|
|
|
|
wxString SendJob::get_http_error_msg(unsigned int status, std::string body)
|
|
{
|
|
int code = 0;
|
|
std::string error;
|
|
std::string message;
|
|
wxString result;
|
|
if (status >= 400 && status < 500)
|
|
try {
|
|
json j = json::parse(body);
|
|
if (j.contains("code")) {
|
|
if (!j["code"].is_null())
|
|
code = j["code"].get<int>();
|
|
}
|
|
if (j.contains("error")) {
|
|
if (!j["error"].is_null())
|
|
error = j["error"].get<std::string>();
|
|
}
|
|
if (j.contains("message")) {
|
|
if (!j["message"].is_null())
|
|
message = j["message"].get<std::string>();
|
|
}
|
|
}
|
|
catch (...) {
|
|
;
|
|
}
|
|
else if (status == 503) {
|
|
return _L("Service Unavailable");
|
|
}
|
|
else {
|
|
wxString unkown_text = _L("Unknown Error.");
|
|
unkown_text += wxString::Format("status=%u, body=%s", status, body);
|
|
return unkown_text;
|
|
}
|
|
|
|
BOOST_LOG_TRIVIAL(error) << "http_error: status=" << status << ", code=" << code << ", error=" << error;
|
|
|
|
result = wxString::Format("code=%u, error=%s", code, from_u8(error));
|
|
return result;
|
|
}
|
|
|
|
inline std::string get_transform_string(int bytes)
|
|
{
|
|
float ms = (float)bytes / 1024.0f / 1024.0f;
|
|
float ks = (float)bytes / 1024.0f;
|
|
char buffer[32];
|
|
if (ms > 0)
|
|
::sprintf(buffer, "%.1fM", ms);
|
|
else if (ks > 0)
|
|
::sprintf(buffer, "%.1fK", ks);
|
|
else
|
|
::sprintf(buffer, "%.1fK", ks);
|
|
return buffer;
|
|
}
|
|
|
|
void SendJob::process(Ctl &ctl)
|
|
{
|
|
BBL::PrintParams params;
|
|
std::string msg;
|
|
int curr_percent = 10;
|
|
NetworkAgent* m_agent = wxGetApp().getAgent();
|
|
AppConfig* config = wxGetApp().app_config;
|
|
int result = -1;
|
|
std::string http_body;
|
|
|
|
if (this->connection_type == "lan") {
|
|
msg = _u8L("Sending print job over LAN");
|
|
}
|
|
else {
|
|
msg = _u8L("Sending print job through cloud service");
|
|
}
|
|
|
|
ctl.call_on_main_thread([this] { prepare(); }).wait();
|
|
ctl.update_status(0, msg);
|
|
int total_plate_num = m_plater->get_partplate_list().get_plate_count();
|
|
|
|
PartPlate* plate = m_plater->get_partplate_list().get_plate(job_data.plate_idx);
|
|
if (plate == nullptr) {
|
|
if (job_data.plate_idx == PLATE_ALL_IDX) {
|
|
//all plate
|
|
for (int index = 0; index < total_plate_num; index++)
|
|
{
|
|
PartPlate* plate_n = m_plater->get_partplate_list().get_plate(index);
|
|
if (plate_n && plate_n->is_valid_gcode_file())
|
|
{
|
|
plate = plate_n;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
plate = m_plater->get_partplate_list().get_curr_plate();
|
|
}
|
|
if (plate == nullptr) {
|
|
BOOST_LOG_TRIVIAL(error) << "can not find plate with valid gcode file when sending to print, plate_index="<< job_data.plate_idx;
|
|
ctl.update_status(curr_percent, check_gcode_failed_str);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* check gcode is valid */
|
|
if (!plate->is_valid_gcode_file()) {
|
|
ctl.update_status(curr_percent, check_gcode_failed_str);
|
|
return;
|
|
}
|
|
|
|
if (ctl.was_canceled()) {
|
|
ctl.update_status(curr_percent, printjob_cancel_str);
|
|
return;
|
|
}
|
|
|
|
std::string project_name = wxGetApp().plater()->get_project_name().ToUTF8().data();
|
|
int curr_plate_idx = 0;
|
|
if (job_data.plate_idx >= 0)
|
|
curr_plate_idx = job_data.plate_idx + 1;
|
|
else if (job_data.plate_idx == PLATE_CURRENT_IDX)
|
|
curr_plate_idx = m_plater->get_partplate_list().get_curr_plate_index() + 1;
|
|
|
|
params.dev_id = m_dev_id;
|
|
params.project_name = m_project_name + ".gcode.3mf";
|
|
params.preset_name = wxGetApp().preset_bundle->prints.get_selected_preset_name();
|
|
params.filename = job_data._3mf_path.string();
|
|
params.config_filename = job_data._3mf_config_path.string();
|
|
params.plate_index = curr_plate_idx;
|
|
params.ams_mapping = this->task_ams_mapping;
|
|
params.connection_type = this->connection_type;
|
|
params.task_use_ams = this->task_use_ams;
|
|
|
|
// local print access
|
|
params.dev_ip = m_dev_ip;
|
|
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_for_mqtt;
|
|
wxString error_text;
|
|
std::string msg_text;
|
|
|
|
const int StagePercentPoint[(int)PrintingStageFinished + 1] = {
|
|
20, // PrintingStageCreate
|
|
30, // PrintingStageUpload
|
|
99, // PrintingStageWaiting
|
|
99, // PrintingStageRecord
|
|
99, // PrintingStageSending
|
|
100, // PrintingStageFinished
|
|
100 // PrintingStageFinished
|
|
};
|
|
|
|
auto update_fn = [this, &ctl,
|
|
&msg, &curr_percent, &error_text, StagePercentPoint](int stage, int code, std::string info) {
|
|
if (stage == SendingPrintJobStage::PrintingStageCreate) {
|
|
if (this->connection_type == "lan") {
|
|
msg = _u8L("Sending G-code file over LAN");
|
|
} else {
|
|
msg = _u8L("Sending G-code file to SD card");
|
|
}
|
|
}
|
|
else if (stage == SendingPrintJobStage::PrintingStageUpload) {
|
|
if (code >= 0 && code <= 100 && !info.empty()) {
|
|
if (this->connection_type == "lan") {
|
|
msg = _u8L("Sending G-code file over LAN");
|
|
}
|
|
else {
|
|
msg = _u8L("Sending G-code file to SD card");
|
|
}
|
|
if (!info.empty()) {
|
|
msg += format("(%s)", info);
|
|
}
|
|
}
|
|
}
|
|
else if (stage == SendingPrintJobStage::PrintingStageFinished) {
|
|
msg = format(_u8L("Successfully sent. Close current page in %s s"), info);
|
|
}
|
|
else {
|
|
if (this->connection_type == "lan") {
|
|
msg = _u8L("Sending G-code file over LAN");
|
|
}
|
|
else {
|
|
msg = _u8L("Sending G-code file over LAN");
|
|
}
|
|
}
|
|
|
|
// update current percnet
|
|
if (stage >= 0 && stage <= (int) PrintingStageFinished) {
|
|
curr_percent = StagePercentPoint[stage];
|
|
if ((stage == BBL::SendingPrintJobStage::PrintingStageUpload) &&
|
|
(code > 0 && code <= 100)) {
|
|
curr_percent = (StagePercentPoint[stage + 1] - StagePercentPoint[stage]) * code / 100 + StagePercentPoint[stage];
|
|
}
|
|
}
|
|
|
|
//get errors
|
|
if (code > 100 || code < 0 || stage == BBL::SendingPrintJobStage::PrintingStageERROR) {
|
|
if (code == BAMBU_NETWORK_ERR_PRINT_WR_FILE_OVER_SIZE || code == BAMBU_NETWORK_ERR_PRINT_SP_FILE_OVER_SIZE) {
|
|
m_plater->update_print_error_info(code, desc_file_too_large, info);
|
|
}
|
|
else if (code == BAMBU_NETWORK_ERR_PRINT_WR_FILE_NOT_EXIST || code == BAMBU_NETWORK_ERR_PRINT_SP_FILE_NOT_EXIST) {
|
|
m_plater->update_print_error_info(code, desc_fail_not_exist, info);
|
|
}
|
|
else if (code == BAMBU_NETWORK_ERR_PRINT_LP_UPLOAD_FTP_FAILED || code == BAMBU_NETWORK_ERR_PRINT_SG_UPLOAD_FTP_FAILED) {
|
|
m_plater->update_print_error_info(code, desc_upload_ftp_failed, info);
|
|
}
|
|
else {
|
|
m_plater->update_print_error_info(code, desc_network_error, info);
|
|
}
|
|
}
|
|
else {
|
|
ctl.update_status(curr_percent, msg);
|
|
}
|
|
};
|
|
|
|
auto cancel_fn = [&ctl]() {
|
|
return ctl.was_canceled();
|
|
};
|
|
|
|
|
|
if (params.connection_type != "lan") {
|
|
if (params.dev_ip.empty())
|
|
params.comments = "no_ip";
|
|
else if (this->cloud_print_only)
|
|
params.comments = "low_version";
|
|
else if (!this->has_sdcard)
|
|
params.comments = "no_sdcard";
|
|
else if (params.password.empty())
|
|
params.comments = "no_password";
|
|
|
|
if (!params.password.empty()
|
|
&& !params.dev_ip.empty()
|
|
&& this->has_sdcard) {
|
|
// try to send local with record
|
|
BOOST_LOG_TRIVIAL(info) << "send_job: try to send gcode to printer";
|
|
ctl.update_status(curr_percent, _u8L("Sending G-code file over LAN"));
|
|
result = m_agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn, nullptr);
|
|
if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
|
|
params.comments = "upload_failed";
|
|
} else {
|
|
params.comments = (boost::format("failed(%1%)") % result).str();
|
|
}
|
|
if (result < 0) {
|
|
// try to send with cloud
|
|
BOOST_LOG_TRIVIAL(info) << "send_job: try to send gcode file to printer";
|
|
ctl.update_status(curr_percent, _u8L("Sending G-code file over LAN"));
|
|
}
|
|
} else {
|
|
BOOST_LOG_TRIVIAL(info) << "send_job: try to send gcode file to printer";
|
|
ctl.update_status(curr_percent, _u8L("Sending G-code file over LAN"));
|
|
}
|
|
} else {
|
|
if (this->has_sdcard) {
|
|
ctl.update_status(curr_percent, _u8L("Sending G-code file over LAN"));
|
|
result = m_agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn, nullptr);
|
|
} else {
|
|
ctl.update_status(curr_percent, _u8L("An SD card needs to be inserted before sending to printer."));
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (ctl.was_canceled()) {
|
|
ctl.update_status(curr_percent, printjob_cancel_str);
|
|
return;
|
|
}
|
|
|
|
if (result < 0) {
|
|
curr_percent = -1;
|
|
|
|
if (result == BAMBU_NETWORK_ERR_PRINT_WR_FILE_NOT_EXIST || result == BAMBU_NETWORK_ERR_PRINT_SP_FILE_NOT_EXIST) {
|
|
msg_text = file_is_not_exists_str;
|
|
}
|
|
else if (result == BAMBU_NETWORK_ERR_PRINT_SP_FILE_OVER_SIZE || result == BAMBU_NETWORK_ERR_PRINT_WR_FILE_OVER_SIZE) {
|
|
msg_text = file_over_size_str;
|
|
}
|
|
else if (result == BAMBU_NETWORK_ERR_PRINT_WR_CHECK_MD5_FAILED || result == BAMBU_NETWORK_ERR_PRINT_SP_CHECK_MD5_FAILED) {
|
|
msg_text = failed_in_cloud_service_str;
|
|
}
|
|
else if (result == BAMBU_NETWORK_ERR_PRINT_WR_GET_NOTIFICATION_TIMEOUT || result == BAMBU_NETWORK_ERR_PRINT_SP_GET_NOTIFICATION_TIMEOUT) {
|
|
msg_text = timeout_to_upload_str;
|
|
}
|
|
else if (result == BAMBU_NETWORK_ERR_PRINT_LP_UPLOAD_FTP_FAILED || result == BAMBU_NETWORK_ERR_PRINT_SG_UPLOAD_FTP_FAILED) {
|
|
msg_text = upload_ftp_failed_str;
|
|
}
|
|
else if (result == BAMBU_NETWORK_ERR_CANCELED) {
|
|
msg_text = print_canceled_str;
|
|
}
|
|
else {
|
|
msg_text = send_print_failed_str;
|
|
}
|
|
|
|
if (result != BAMBU_NETWORK_ERR_CANCELED) {
|
|
ctl.show_error_info(msg_text, 0, "", "");
|
|
}
|
|
BOOST_LOG_TRIVIAL(error) << "send_job: failed, result = " << result;
|
|
|
|
}
|
|
else {
|
|
BOOST_LOG_TRIVIAL(error) << "send_job: send ok.";
|
|
wxCommandEvent* evt = new wxCommandEvent(m_print_job_completed_id);
|
|
evt->SetString(from_u8(params.project_name));
|
|
wxQueueEvent(m_plater, evt);
|
|
m_job_finished = true;
|
|
}
|
|
}
|
|
|
|
void SendJob::on_success(std::function<void()> success)
|
|
{
|
|
m_success_fun = success;
|
|
}
|
|
|
|
void SendJob::on_check_ip_address_fail(std::function<void(int)> func)
|
|
{
|
|
m_enter_ip_address_fun_fail = func;
|
|
}
|
|
|
|
void SendJob::on_check_ip_address_success(std::function<void()> func)
|
|
{
|
|
m_enter_ip_address_fun_success = func;
|
|
}
|
|
|
|
|
|
void SendJob::finalize(bool canceled, std::exception_ptr &eptr)
|
|
{
|
|
try {
|
|
if (eptr)
|
|
std::rethrow_exception(eptr);
|
|
eptr = nullptr;
|
|
} catch (...) {
|
|
eptr = std::current_exception();
|
|
}
|
|
|
|
if (canceled || eptr)
|
|
return;
|
|
}
|
|
|
|
void SendJob::set_project_name(std::string name)
|
|
{
|
|
m_project_name = name;
|
|
}
|
|
|
|
}} // namespace Slic3r::GUI
|