161{
162
163 std::string msg;
164 int curr_percent = 10;
165 NetworkAgent* m_agent = wxGetApp().getAgent();
166 AppConfig* config = wxGetApp().app_config;
167
169 msg =
_u8L(
"Sending print job over LAN");
170 }
171 else {
172 msg =
_u8L(
"Sending print job through cloud service");
173 }
174
175 ctl.update_status(0, msg);
176 ctl.call_on_main_thread([
this] {
prepare(); }).wait();
177
178 int result = -1;
179 std::string http_body;
180
181 const auto mark_lifecycle_started = [this]() {
183 return;
184
185 LifecycleEventContext start_ctx;
188 start_ctx.source = "print_job";
191 };
192
195 total_plate_num =
m_plater->get_partplate_list().get_plate_count();
196 PartPlate *plate =
m_plater->get_partplate_list().get_plate(
job_data.plate_idx);
197 if (plate == nullptr) {
198 plate =
m_plater->get_partplate_list().get_curr_plate();
199 if (plate == nullptr) return;
200 }
201
202
203 if (!plate->is_valid_gcode_file() &&
m_print_type ==
"from_normal") {
205 return;
206 }
207
208 if (ctl.was_canceled()) {
210 return;
211 }
212 }
213
215 int curr_plate_idx = 0;
216
221 curr_plate_idx =
job_data.plate_idx + 1;
223 curr_plate_idx =
m_plater->get_partplate_list().get_curr_plate_index() + 1;
225 curr_plate_idx =
m_plater->get_partplate_list().get_curr_plate_index() + 1;
226 else
227 curr_plate_idx =
m_plater->get_partplate_list().get_curr_plate_index() + 1;
228 }
231 }
232
233 PartPlate* curr_plate =
m_plater->get_partplate_list().get_curr_plate();
234 if (curr_plate) {
236 }
237
238 PrintParams params;
239
240
244 params.username = m_agent->default_lan_username();
246
247
249 bool emmc_ok = false;
250 bool ftp_ok = false;
254 std::string url = "bambu:///local/" + devIP + "?port=6000&user=" + "bblp" + "&passwd=" + accessCode;
255 try {
256 std::unique_ptr<FileTransferTunnel> tunnel = std::make_unique<FileTransferTunnel>(
module(), url);
257 emmc_ok = tunnel->sync_start_connect();
258 } catch (const std::exception &e) {
259 BOOST_LOG_TRIVIAL(warning) << "eMMC tunnel unavailable, falling back to FTP: " << e.what();
260 emmc_ok = false;
261 }
262 }
263 {
265 params.project_name = "verify_job";
266 params.filename =
job_data._temp_path.string();
268
269 result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr, nullptr);
270
271 ftp_ok = result == 0;
272 }
273 if (!emmc_ok && !ftp_ok) {
275 BOOST_LOG_TRIVIAL(error) << "LAN connection verification failed:"
276 << " emmc_ok=" << emmc_ok
277 << ", ftp_ok=" << ftp_ok
278 << ", ftp_result=" << result
282 << ", legacy_mode=" << (legacy_mode ? "true" : "false");
285 return;
286 }
287
288 params.project_name = "";
289 params.filename = "";
290 }
291
294 params.filename =
job_data._3mf_path.string();
295 params.config_filename =
job_data._3mf_config_path.string();
296 params.plate_index = curr_plate_idx;
317
318
319
320
321 bool disable_emmc = true;
322 if (wxGetApp().app_config) {
323 auto v = wxGetApp().app_config->get("disable_emmc_print");
324 if (v == "0" || v == "false")
325 disable_emmc = false;
326 }
328
331 }
332
333 if (wxGetApp().model().model_info && wxGetApp().model().model_info.get()) {
334 ModelInfo* model_info = wxGetApp().model().model_info.get();
336 if (origin_profile_id != model_info->metadata_items.end()) {
337 try {
338 params.origin_profile_id = std::stoi(origin_profile_id->second.c_str());
339 }
340 catch(...) {}
341 }
343 if (origin_model_id != model_info->metadata_items.end()) {
344 try {
345 params.origin_model_id = origin_model_id->second;
346 }
347 catch(...) {}
348 }
349
351 if (profile_name != model_info->metadata_items.end()) {
352 try {
353 params.preset_name = profile_name->second;
354 }
355 catch (...) {}
356 }
357
360 if (model_name != model_info->metadata_items.end()) {
361 try {
362 std::string mall_model_name = model_name->second;
363 std::replace(mall_model_name.begin(), mall_model_name.end(), ' ', '_');
364 const char *unusable_symbols = "<>[]:/\\|?*\" ";
365 for (const char *symbol = unusable_symbols; *symbol != '\0'; ++symbol) { std::replace(mall_model_name.begin(), mall_model_name.end(), *symbol, '_'); }
366
367 std::regex pattern("_+");
368 params.project_name = std::regex_replace(mall_model_name, pattern, "_");
370 } catch (...) {}
371 }
372 }
373 }
374
375 params.stl_design_id = 0;
376 if (!wxGetApp().model().stl_design_id.empty()) {
377
378 auto country_code = wxGetApp().app_config->get_country_code();
379 bool match_code = false;
380
381 if (wxGetApp().model().stl_design_country == "DEV" && (country_code == "ENV_CN_DEV" || country_code == "NEW_ENV_DEV_HOST")) {
382 match_code = true;
383 }
384
385 if (wxGetApp().model().stl_design_country == "QA" && (country_code == "ENV_CN_QA" || country_code == "NEW_ENV_QAT_HOST")) {
386 match_code = true;
387 }
388
389 if (wxGetApp().model().stl_design_country == "CN_PRE" && (country_code == "ENV_CN_PRE" || country_code == "NEW_ENV_PRE_HOST")) {
390 match_code = true;
391 }
392
393 if (wxGetApp().model().stl_design_country == "US_PRE" && country_code == "ENV_US_PRE") {
394 match_code = true;
395 }
396
397 if (country_code == wxGetApp().model().stl_design_country) {
398 match_code = true;
399 }
400
401 if (match_code) {
402 int stl_design_id = 0;
403 try {
404 stl_design_id = std::stoi(wxGetApp().model().stl_design_id);
405 }
406 catch (const std::exception&) {
407 stl_design_id = 0;
408 }
409 params.stl_design_id = stl_design_id;
410 }
411 }
412
413 if (params.preset_name.empty() &&
m_print_type ==
"from_normal") { params.preset_name = wxString::Format(
"%s_plate_%d", transport_project_name, curr_plate_idx).ToStdString(); }
414 if (params.project_name.empty()) {params.project_name = transport_project_name;}
415
417 params.project_name = transport_project_name;
418 params.origin_model_id = "";
419 }
420
421 wxString error_text;
422 std::string msg_text;
423
424
426 20,
427 30,
428 70,
429 75,
430 97,
431 100,
432 100
433 };
434
435 bool is_try_lan_mode = false;
436 bool is_try_lan_mode_failed = false;
437
438 auto update_fn = [this, &ctl,
439 &is_try_lan_mode,
440 &is_try_lan_mode_failed,
441 &msg,
442 &curr_percent,
443 StagePercentPoint
444 ](int stage, int code, std::string info) {
445
448 msg =
_u8L(
"Sending print job over LAN");
449 } else {
450 msg =
_u8L(
"Sending print job through cloud service");
451 }
452 }
454 if (code >= 0 && code <= 100 && !info.empty()) {
456 msg =
_u8L(
"Sending print job over LAN");
457 } else {
458 msg =
_u8L(
"Sending print job through cloud service");
459 }
460 msg +=
format(
"(%s)", info);
461 }
462 }
465 msg =
_u8L(
"Sending print job over LAN");
466 } else {
467 msg =
_u8L(
"Sending print job through cloud service");
468 }
469 }
471 msg =
_u8L(
"Sending print configuration");
472 }
475 msg =
_u8L(
"Sending print job over LAN");
476 } else {
477 msg =
_u8L(
"Sending print job through cloud service");
478 }
479 }
481 msg =
format(
_u8L(
"Successfully sent. Will automatically jump to the device page in %ss"), info);
483 msg =
format(
_u8L(
"Successfully sent. Will automatically jump to the next page in %ss"), info);
484 }
485 ctl.clear_percent();
486 } else {
488 msg =
_u8L(
"Sending print job over LAN");
489 } else {
490 msg =
_u8L(
"Sending print job through cloud service");
491 }
492 }
493
494
496 curr_percent = StagePercentPoint[stage];
499 && (code > 0 && code <= 100)) {
500 curr_percent = (StagePercentPoint[stage + 1] - StagePercentPoint[stage]) * code / 100 + StagePercentPoint[stage];
501 }
502 }
503
504
512 }else {
514 }
515 }
516 else {
517 ctl.update_status(curr_percent, msg);
518 }
519 };
520
521 auto cancel_fn = [&ctl]() {
522 return ctl.was_canceled();
523 };
524
525
526 DeviceManager* dev = wxGetApp().getDeviceManager();
527 MachineObject* obj = dev->get_selected_machine();
528
529 auto wait_fn = [&ctl, &obj](int state, std::string job_info) {
530 BOOST_LOG_TRIVIAL(info) << "print_job: get_job_info = " << job_info;
531
532 if (!obj->is_support_wait_sending_finish) {
533 return true;
534 }
535
536 std::string curr_job_id;
538 try {
539 std::ignore = job_info_j.parse(job_info);
540 if (job_info_j.contains("job_id")) {
542 }
543 BOOST_LOG_TRIVIAL(
trace) <<
"print_job: curr_obj_id=" << curr_job_id;
544
545 } catch(...) {
546 ;
547 }
548
549 if (obj) {
552 BOOST_LOG_TRIVIAL(
trace) <<
"print_job: obj job_id = " << obj->job_id_;
553 if (!obj->job_id_.empty() && obj->job_id_.compare(curr_job_id) == 0) {
554 BOOST_LOG_TRIVIAL(info) <<
"print_job: got job_id = " << obj->job_id_ <<
", time_out=" <<
time_out;
555 return true;
556 }
557 if (obj->is_in_printing_status(obj->print_status)) {
558 BOOST_LOG_TRIVIAL(info) << "print_job: printer has enter printing status, s = " << obj->print_status;
559 return true;
560 }
561
562 if (ctl.was_canceled()) {
563 BOOST_LOG_TRIVIAL(info) << "print_job: user cancel the job " << obj->job_id_;
564 return true;
565 }
567 boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
568 }
569
570
571 BOOST_LOG_TRIVIAL(info) << "print_job: timeout, cancel the job" << obj->job_id_;
572
573
574
575 return true;
576 }
577 BOOST_LOG_TRIVIAL(info) << "print_job: obj is null";
578 return true;
579 };
580
582 BOOST_LOG_TRIVIAL(info) << "print_job: try to send with cloud, model is sdcard view";
583 ctl.update_status(curr_percent,
_u8L(
"Sending print job through cloud service"));
584 mark_lifecycle_started();
585 result = m_agent->start_sdcard_print(params, update_fn, cancel_fn);
586 } else if (params.connection_type != "lan") {
587 if (params.dev_ip.empty())
588 params.comments = "no_ip";
590 params.comments = "low_version";
592 params.comments = "no_sdcard";
593 else if (params.password.empty())
594 params.comments = "no_password";
595
596
597
598 if (!wxGetApp().app_config->get("lan_mode_only").empty() && wxGetApp().app_config->get("lan_mode_only") == "1") {
599
600 if (params.password.empty() || params.dev_ip.empty()) {
601 error_text = wxString::Format(
_L(
"Access code:%s IP address:%s"), params.password, params.dev_ip);
603 }
604 else {
605 BOOST_LOG_TRIVIAL(info) << "print_job: use ftp send print only";
606 ctl.update_status(curr_percent,
_u8L(
"Sending print job over LAN"));
607 is_try_lan_mode = true;
608 mark_lifecycle_started();
609 result = m_agent->start_local_print_with_record(params, update_fn, cancel_fn, wait_fn);
610 if (result < 0) {
611 error_text = wxString::Format(
_L(
"Access code:%s IP address:%s"), params.password, params.dev_ip);
612
613 BOOST_LOG_TRIVIAL(warning) << "print_job: use ftp send print failed";
614 }
615 }
616 }
617 else {
619 && !params.password.empty()
620 && !params.dev_ip.empty()
621 && this->has_sdcard) {
622
623 BOOST_LOG_TRIVIAL(info) << "print_job: try to start local print with record";
624 ctl.update_status(curr_percent,
_u8L(
"Sending print job over LAN"));
625 mark_lifecycle_started();
626 result = m_agent->start_local_print_with_record(params, update_fn, cancel_fn, wait_fn);
627 if (result == 0) {
628 params.comments = "";
629 }
631 params.comments = "upload_failed";
632 }
633 else {
634 params.comments = (boost::format("failed(%1%)") % result).str();
635 }
636 if (result < 0) {
637 is_try_lan_mode_failed = true;
638
639 BOOST_LOG_TRIVIAL(warning) << "print_job: try to send with cloud";
640 ctl.update_status(curr_percent,
_u8L(
"Sending print job through cloud service"));
641
642 result = m_agent->start_print(params, update_fn, cancel_fn, wait_fn);
643 }
644 }
645 else {
646 BOOST_LOG_TRIVIAL(info) << "print_job: send with cloud";
647 ctl.update_status(curr_percent,
_u8L(
"Sending print job through cloud service"));
648 mark_lifecycle_started();
649 result = m_agent->start_print(params, update_fn, cancel_fn, wait_fn);
650 }
651 }
652 } else {
654 ctl.update_status(curr_percent,
_u8L(
"Sending print job over LAN"));
655 mark_lifecycle_started();
656 result = m_agent->start_local_print(params, update_fn, cancel_fn);
657 } else {
660 ctl.update_status(curr_percent,
_u8L(
"A Storage needs to be inserted before printing via LAN."));
661 return;
664
665 ctl.update_status(curr_percent,
_u8L(
"Sending print job over LAN, but the Storage in the printer is abnormal and print-issues may be caused by this."));
666 mark_lifecycle_started();
667 result = m_agent->start_local_print(params, update_fn, cancel_fn);
668 break;
669 }
670 ctl.update_status(curr_percent,
_u8L(
"The Storage in the printer is abnormal. Please replace it with a normal Storage before sending print job to printer."));
671 return;
673 ctl.update_status(curr_percent,
_u8L(
"The Storage in the printer is read-only. Please replace it with a normal Storage before sending print job to printer."));
674 return;
676 ctl.update_status(curr_percent,
_u8L(
"Sending print job over LAN"));
677 mark_lifecycle_started();
678 result = m_agent->start_local_print(params, update_fn, cancel_fn);
679 break;
680 default:
681 ctl.update_status(curr_percent,
_u8L(
"Encountered an unknown error with the Storage status. Please try again."));
682 return;
683 }
684 }
685 }
686
687 if (result < 0) {
688 curr_percent = -1;
689
690
691
693 msg_text =
_u8L(
"Retrieving printer information, please try again later.");
706 ctl.update_status(0, msg_text);
707 } else {
709 }
710
712 ctl.show_error_info(msg_text, 0, "", "");
713 }
714
715 BOOST_LOG_TRIVIAL(error) << "print_job: failed, result = " << result;
716 } else {
717
718
719 BOOST_LOG_TRIVIAL(error) << "print_job: send ok.";
723 else
726 int sel = wxGetApp().mainframe->get_calibration_curr_tab();
727 if (sel >= 0) {
728 evt->SetInt(sel);
729 }
730 }
734 }
735}
#define PLATE_ALL_IDX
Definition PartPlate.hpp:57
#define PLATE_CURRENT_IDX
Definition PartPlate.hpp:56
#define PRINT_JOB_SENDING_TIMEOUT
Definition PrintJob.hpp:20
#define BAMBU_NETOWRK_ERR_PRINT_SP_ENC_FLAG_NOT_READY
Definition bambu_networking.hpp:85
#define BAMBU_NETWORK_ERR_PRINT_LP_UPLOAD_FTP_FAILED
Definition bambu_networking.hpp:89
#define BAMBU_NETWORK_ERR_PRINT_SP_GET_NOTIFICATION_TIMEOUT
Definition bambu_networking.hpp:76
#define BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED
Definition bambu_networking.hpp:36
#define BAMBU_NETWORK_ERR_CANCELED
Definition bambu_networking.hpp:34
#define BAMBU_NETWORK_ERR_PRINT_SP_FILE_OVER_SIZE
Definition bambu_networking.hpp:80
#define BAMBU_NETWORK_ERR_PRINT_SP_CHECK_MD5_FAILED
Definition bambu_networking.hpp:73
#define BAMBU_NETWORK_ERR_PRINT_SG_UPLOAD_FTP_FAILED
Definition bambu_networking.hpp:93
#define BAMBU_NETWORK_ERR_PRINT_WR_FILE_NOT_EXIST
Definition bambu_networking.hpp:65
#define BAMBU_NETWORK_ERR_PRINT_WR_GET_NOTIFICATION_TIMEOUT
Definition bambu_networking.hpp:61
#define BAMBU_NETWORK_ERR_PRINT_SP_FILE_NOT_EXIST
Definition bambu_networking.hpp:78
#define BAMBU_NETWORK_ERR_PRINT_WR_UPLOAD_FTP_FAILED
Definition bambu_networking.hpp:68
#define BAMBU_NETWORK_ERR_PRINT_WR_FILE_OVER_SIZE
Definition bambu_networking.hpp:59
#define BAMBU_NETWORK_ERR_PRINT_WR_CHECK_MD5_FAILED
Definition bambu_networking.hpp:57
#define BBL_DESIGNER_PROFILE_ID_TAG
Definition bbs_3mf.hpp:47
#define BBL_DESIGNER_MODEL_TITLE_TAG
Definition bbs_3mf.hpp:46
#define BBL_DESIGNER_MODEL_ID_TAG
Definition bbs_3mf.hpp:49
#define BBL_DESIGNER_PROFILE_TITLE_TAG
Definition bbs_3mf.hpp:48
bool use_legacy_network() const
Definition BBLNetworkPlugin.hpp:304
static BBLNetworkPlugin & instance()
Definition BBLNetworkPlugin.cpp:56
static std::string get_longlong_val(const nlohmann::json &j)
Definition DevUtil.cpp:173
@ HAS_SDCARD_NORMAL
Definition DevStorage.h:19
@ HAS_SDCARD_ABNORMAL
Definition DevStorage.h:20
@ HAS_SDCARD_READONLY
Definition DevStorage.h:21
@ NO_SDCARD
Definition DevStorage.h:18
std::string connection_type
Definition PrintJob.hpp:75
PlateListData plate_data
Definition PrintJob.hpp:60
bool m_local_use_ssl
Definition PrintJob.hpp:83
bool could_emmc_print
Definition PrintJob.hpp:93
bool task_vibration_cali
Definition PrintJob.hpp:87
bool task_use_ams
Definition PrintJob.hpp:94
int auto_offset_cali
Definition PrintJob.hpp:101
bool task_timelapse_use_internal
Definition PrintJob.hpp:89
bool task_flow_cali
Definition PrintJob.hpp:86
std::string m_print_type
Definition PrintJob.hpp:76
std::string task_ams_mapping2
Definition PrintJob.hpp:72
std::string truncate_string(const std::string &str, size_t maxLength)
Definition PrintJob.cpp:93
bool m_local_use_ssl_for_ftp
Definition PrintJob.hpp:84
bool cloud_print_only
Definition PrintJob.hpp:91
int extruder_cali_manual_mode
Definition PrintJob.hpp:102
bool task_record_timelapse
Definition PrintJob.hpp:88
std::string task_ams_mapping
Definition PrintJob.hpp:71
std::string task_ams_mapping_info
Definition PrintJob.hpp:73
bool task_layer_inspect
Definition PrintJob.hpp:90
void prepare()
Definition PrintJob.cpp:78
int m_print_from_sdc_plate_idx
Definition PrintJob.hpp:81
bool task_ext_change_assist
Definition PrintJob.hpp:97
int auto_bed_leveling
Definition PrintJob.hpp:99
std::string m_dst_path
Definition PrintJob.hpp:77
wxString m_completed_evt_data
Definition PrintJob.hpp:53
std::string m_ftp_folder
Definition PrintJob.hpp:67
std::string task_bed_type
Definition PrintJob.hpp:69
bool has_sdcard
Definition PrintJob.hpp:92
std::string task_nozzles_info
Definition PrintJob.hpp:74
DevStorage::SdcardState sdcard_state
Definition PrintJob.hpp:96
std::string task_nozzle_mapping
Definition PrintJob.hpp:70
int auto_flow_cali
Definition PrintJob.hpp:100
bool task_bed_leveling
Definition PrintJob.hpp:85
std::string m_dev_ip
Definition PrintJob.hpp:66
std::string m_access_code
Definition PrintJob.hpp:68
static auto upload_ftp_failed_str
Definition PrintJob.cpp:55
static auto desc_file_too_large
Definition PrintJob.cpp:58
constexpr int time_out
Definition FanControl.cpp:41
static Plater * plater()
Definition GUI_Factories.cpp:400
static auto desc_fail_not_exist
Definition PrintJob.cpp:59
static auto printjob_cancel_str
Definition PrintJob.cpp:48
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:36
static auto file_over_size_str
Definition PrintJob.cpp:52
static auto desc_network_error
Definition PrintJob.cpp:57
static auto print_canceled_str
Definition PrintJob.cpp:53
static auto failed_in_cloud_service_str
Definition PrintJob.cpp:50
static auto timeout_to_upload_str
Definition PrintJob.cpp:49
static auto file_is_not_exists_str
Definition PrintJob.cpp:51
static auto desc_upload_ftp_failed
Definition PrintJob.cpp:61
static auto check_gcode_failed_str
Definition PrintJob.cpp:47
static auto send_print_failed_str
Definition PrintJob.cpp:54
@ PrintingStageSending
Definition bambu_networking.hpp:151
@ PrintingStageCreate
Definition bambu_networking.hpp:148
@ PrintingStageFinished
Definition bambu_networking.hpp:154
@ PrintingStageUpload
Definition bambu_networking.hpp:149
@ PrintingStageWaiting
Definition bambu_networking.hpp:150
@ PrintingStageERROR
Definition bambu_networking.hpp:155
@ PrintingStageRecord
Definition bambu_networking.hpp:152
@ PrintJobStarted
Definition LifecycleEvents.hpp:60
static std::string bed_type_to_gcode_string(const BedType type)
Definition PrintConfig.hpp:701
FileTransferModule & module()
Definition FileTransferUtils.hpp:248
#define _u8L(s)
Definition I18N.hpp:11