From a5c6450cc51b28aa747d967ee48e8df5d9ddce75 Mon Sep 17 00:00:00 2001 From: "xin.zhang" Date: Thu, 3 Jul 2025 15:20:57 +0800 Subject: [PATCH] ENH: support command error dialog; support clean print error; support stop ams drying JIRA: [STUDIO-12441] [STUDIO-13123] [STUDIO-12372] Change-Id: I87170f1f51c1e24f6eee61deb07d06ff6b53a884 (cherry picked from commit 1ec5382f14ebf06d8f3ed128e377243665434ca6) --- localization/i18n/list.txt | 1 + src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/DeviceErrorDialog.cpp | 378 +++++++++++++++++++++++++++ src/slic3r/GUI/DeviceErrorDialog.hpp | 88 +++++++ src/slic3r/GUI/DeviceManager.cpp | 76 ++++++ src/slic3r/GUI/DeviceManager.hpp | 15 ++ src/slic3r/GUI/MainFrame.cpp | 4 +- src/slic3r/GUI/Monitor.cpp | 14 +- src/slic3r/GUI/Monitor.hpp | 4 +- src/slic3r/GUI/ReleaseNote.cpp | 1 + src/slic3r/GUI/ReleaseNote.hpp | 1 + src/slic3r/GUI/StatusPanel.cpp | 24 +- 12 files changed, 603 insertions(+), 5 deletions(-) create mode 100644 src/slic3r/GUI/DeviceErrorDialog.cpp create mode 100644 src/slic3r/GUI/DeviceErrorDialog.hpp diff --git a/localization/i18n/list.txt b/localization/i18n/list.txt index 4be65636b3..78fd545f2b 100644 --- a/localization/i18n/list.txt +++ b/localization/i18n/list.txt @@ -66,6 +66,7 @@ src/slic3r/GUI/BedShapeDialog.cpp src/slic3r/GUI/BedShapeDialog.hpp src/slic3r/GUI/ConfigManipulation.cpp src/slic3r/GUI/DeviceManager.cpp +src/slic3r/GUI/DeviceErrorDialog.cpp src/slic3r/GUI/ExtraRenderers.cpp src/slic3r/GUI/EditGCodeDialog.cpp src/slic3r/GUI/Field.cpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 8732966143..9c7cdfbec3 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -252,6 +252,8 @@ set(SLIC3R_GUI_SOURCES GUI/ImGuiWrapper.hpp GUI/IMSlider.cpp GUI/IMSlider.hpp + GUI/DeviceErrorDialog.hpp + GUI/DeviceErrorDialog.cpp GUI/IMToolbar.cpp GUI/IMToolbar.hpp GUI/InstanceCheck.cpp diff --git a/src/slic3r/GUI/DeviceErrorDialog.cpp b/src/slic3r/GUI/DeviceErrorDialog.cpp new file mode 100644 index 0000000000..355defdd27 --- /dev/null +++ b/src/slic3r/GUI/DeviceErrorDialog.cpp @@ -0,0 +1,378 @@ +#include "DeviceErrorDialog.hpp" +#include "HMS.hpp" + +#include "Widgets/Button.hpp" +#include "GUI_App.hpp" +#include "MainFrame.hpp" + +namespace Slic3r { +namespace GUI +{ + +DeviceErrorDialog::DeviceErrorDialog(MachineObject* obj, wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) + :DPIDialog(parent, id, title, pos, size, style), m_obj(obj) +{ + std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); + SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); + SetBackgroundColour(*wxWHITE); + + SetTitle(_L("Error")); + + auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(350), 1)); + m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); + + m_scroll_area = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL); + m_scroll_area->SetScrollRate(0, 5); + m_scroll_area->SetBackgroundColour(*wxWHITE); + m_scroll_area->SetMinSize(wxSize(FromDIP(320), FromDIP(250))); + + wxBoxSizer* text_sizer = new wxBoxSizer(wxVERTICAL); + + m_error_msg_label = new Label(m_scroll_area, wxEmptyString, LB_AUTO_WRAP); + m_error_picture = new wxStaticBitmap(m_scroll_area, wxID_ANY, wxBitmap(), wxDefaultPosition, wxSize(FromDIP(300), FromDIP(180))); + + //Label* dev_name = new Label(m_scroll_area, wxString::FromUTF8(obj->dev_name) + ":", LB_AUTO_WRAP); + //dev_name->SetMaxSize(wxSize(FromDIP(300), -1)); + //dev_name->SetMinSize(wxSize(FromDIP(300), -1)); + //dev_name->Wrap(FromDIP(300)); + //text_sizer->Add(dev_name, 0, wxALIGN_CENTER, FromDIP(5)); + //text_sizer->AddSpacer(5); + text_sizer->Add(m_error_picture, 0, wxALIGN_CENTER, FromDIP(5)); + text_sizer->AddSpacer(10); + text_sizer->Add(m_error_msg_label, 0, wxALIGN_CENTER, FromDIP(5)); + + m_error_code_label = new Label(m_scroll_area, wxEmptyString, LB_AUTO_WRAP); + text_sizer->AddSpacer(5); + text_sizer->Add(m_error_code_label, 0, wxALIGN_CENTER, FromDIP(5)); + m_scroll_area->SetSizer(text_sizer); + + auto bottom_sizer = new wxBoxSizer(wxVERTICAL); + m_sizer_button = new wxBoxSizer(wxVERTICAL); + bottom_sizer->Add(m_sizer_button, 0, wxEXPAND | wxRIGHT | wxLEFT, 0); + + wxBoxSizer* m_center_sizer = new wxBoxSizer(wxVERTICAL); + m_center_sizer->Add(0, 0, 1, wxTOP, FromDIP(5)); + m_center_sizer->Add(m_scroll_area, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(15)); + m_center_sizer->Add(bottom_sizer, 0, wxEXPAND | wxRIGHT | wxLEFT, FromDIP(20)); + m_center_sizer->Add(0, 0, 0, wxTOP, FromDIP(10)); + + m_sizer_main = new wxBoxSizer(wxVERTICAL); + m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0); + m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5)); + m_sizer_main->Add(m_center_sizer, 0, wxBOTTOM | wxEXPAND, FromDIP(5)); + + SetSizer(m_sizer_main); + Layout(); + m_sizer_main->Fit(this); + + init_button_list(); + + CenterOnParent(); + wxGetApp().UpdateDlgDarkUI(this); + + Bind(wxEVT_WEBREQUEST_STATE, &DeviceErrorDialog::on_webrequest_state, this); +} + +DeviceErrorDialog::~DeviceErrorDialog() +{ + if (web_request.IsOk() && web_request.GetState() == wxWebRequest::State_Active) + { + BOOST_LOG_TRIVIAL(info) << "web_request: cancelled"; + web_request.Cancel(); + } + m_error_picture->SetBitmap(wxBitmap()); +} + +void DeviceErrorDialog::on_webrequest_state(wxWebRequestEvent& evt) +{ + BOOST_LOG_TRIVIAL(trace) << "monitor: monitor_panel web request state = " << evt.GetState(); + switch (evt.GetState()) + { + case wxWebRequest::State_Completed: + { + wxImage img(*evt.GetResponse().GetStream()); + wxImage resize_img = img.Scale(FromDIP(320), FromDIP(180), wxIMAGE_QUALITY_HIGH); + wxBitmap error_prompt_pic = resize_img; + m_error_picture->SetBitmap(error_prompt_pic); + Layout(); + Fit(); + + break; + } + case wxWebRequest::State_Failed: + case wxWebRequest::State_Cancelled: + case wxWebRequest::State_Unauthorized: + { + m_error_picture->SetBitmap(wxBitmap()); + break; + } + case wxWebRequest::State_Active: + case wxWebRequest::State_Idle: break; + default: break; + } +} + +void DeviceErrorDialog::init_button(ActionButton style, wxString buton_text) +{ + if (btn_bg_white.count() == 0) + { + btn_bg_white = StateColor(std::pair(wxColour(206, 206, 206), StateColor::Pressed), + std::pair(wxColour(238, 238, 238), StateColor::Hovered), + std::pair(*wxWHITE, StateColor::Normal)); + } + + Button* print_error_button = new Button(this, buton_text); + print_error_button->SetBackgroundColor(btn_bg_white); + print_error_button->SetBorderColor(wxColour(38, 46, 48)); + print_error_button->SetFont(Label::Body_14); + print_error_button->SetSize(wxSize(FromDIP(300), FromDIP(30))); + print_error_button->SetMinSize(wxSize(FromDIP(300), FromDIP(30))); + print_error_button->SetMaxSize(wxSize(-1, FromDIP(30))); + print_error_button->SetCornerRadius(FromDIP(5)); + print_error_button->Hide(); + m_button_list[style] = print_error_button; + m_button_list[style]->Bind(wxEVT_LEFT_DOWN, [this, style](wxMouseEvent& e) + { + this->on_button_click(style); + e.Skip(); + }); +} + +void DeviceErrorDialog::init_button_list() +{ + init_button(RESUME_PRINTING, _L("Resume Printing")); + init_button(RESUME_PRINTING_DEFECTS, _L("Resume (defects acceptable)")); + init_button(RESUME_PRINTING_PROBELM_SOLVED, _L("Resume (problem solved)")); + init_button(STOP_PRINTING, _L("Stop Printing"));// pop up recheck dialog? + init_button(CHECK_ASSISTANT, _L("Check Assistant")); + init_button(FILAMENT_EXTRUDED, _L("Filament Extruded, Continue")); + init_button(RETRY_FILAMENT_EXTRUDED, _L("Not Extruded Yet, Retry")); + init_button(CONTINUE, _L("Finished, Continue")); + init_button(LOAD_VIRTUAL_TRAY, _L("Load Filament")); + init_button(OK_BUTTON, _L("OK")); + init_button(FILAMENT_LOAD_RESUME, _L("Filament Loaded, Resume")); + init_button(JUMP_TO_LIVEVIEW, _L("View Liveview")); + init_button(NO_REMINDER_NEXT_TIME, _L("No Reminder Next Time")); + init_button(IGNORE_NO_REMINDER_NEXT_TIME, _L("Ignore. Don't Remind Next Time")); + init_button(IGNORE_RESUME, _L("Ignore this and Resume")); + init_button(PROBLEM_SOLVED_RESUME, _L("Problem Solved and Resume")); + init_button(STOP_BUZZER, _L("Stop Buzzer")); + init_button(RETRY_PROBLEM_SOLVED, _L("Retry (problem solved)")); + init_button(STOP_DRYING, _L("Stop Drying")); +} + +void DeviceErrorDialog::on_dpi_changed(const wxRect& suggested_rect) +{ + for (auto used_button : m_used_button) { used_button->Rescale();} + wxGetApp().UpdateDlgDarkUI(this); + Refresh(); +} + +static const std::unordered_set s_jump_liveview_error_codes = { "0300-8003", "0300-8002", "0300-800A"}; +void DeviceErrorDialog::show_error_code(int error_code) +{ + if (m_error_code == error_code) { return;} + if (wxGetApp().get_hms_query()->is_internal_error(m_obj, error_code)) { return;} + + /* error code str*/ + std::string error_str = m_obj->get_error_code_str(error_code); + + /* error code message*/ + wxString error_msg = wxGetApp().get_hms_query()->query_print_error_msg(m_obj, error_code); + if (error_msg.IsEmpty()) { error_msg = _L("Unknown error.");} + + /* action buttons*/ + std::vector used_button; + wxString error_image_url = wxGetApp().get_hms_query()->query_print_image_action(m_obj, error_code, used_button); + if (s_jump_liveview_error_codes.count(error_str)) { used_button.emplace_back(DeviceErrorDialog::JUMP_TO_LIVEVIEW);}// special case + + /* do update*/ + update_contents(error_msg, error_str, error_image_url, used_button); + + wxGetApp().UpdateDlgDarkUI(this); + Show(); + Raise(); + + this->RequestUserAttention(wxUSER_ATTENTION_ERROR); +} + +void DeviceErrorDialog::update_contents(const wxString& text, const wxString& error_code, const wxString& image_url, const std::vector& btns) +{ + if (error_code.empty()) { return; } + + /* buttons*/ + { + m_sizer_button->Clear(); + m_used_button.clear(); + + // Show the used buttons + std::unordered_set shown_btns; + for (int button_id : btns) + { + auto iter = m_button_list.find(button_id); + if (iter != m_button_list.end()) + { + m_sizer_button->Add(iter->second, 0, wxALL, FromDIP(5)); + iter->second->Show(); + m_used_button.insert(iter->second); + } + } + + // Hide unused buttons + for (const auto& pair : m_button_list) + { + if (m_used_button.count(pair.second) == 0) { pair.second->Hide(); } + } + } + + /* image */ + if (!image_url.empty()) + { + const wxImage& img = wxGetApp().get_hms_query()->query_image_from_local(image_url); + if (!img.IsOk() && image_url.Contains("http")) + { + web_request = wxWebSession::GetDefault().CreateRequest(this, image_url); + BOOST_LOG_TRIVIAL(trace) << "monitor: create new webrequest, state = " << web_request.GetState(); + if (web_request.GetState() == wxWebRequest::State_Idle) web_request.Start(); + BOOST_LOG_TRIVIAL(trace) << "monitor: start new webrequest, state = " << web_request.GetState(); + } + else + { + const wxImage& resize_img = img.Scale(FromDIP(320), FromDIP(180), wxIMAGE_QUALITY_HIGH); + m_error_picture->SetBitmap(wxBitmap(resize_img)); + } + + m_error_picture->Show(); + } + else + { + m_error_picture->Hide(); + } + + /* error code*/ + const wxString& show_time = wxDateTime::Now().Format("%H%M%d"); + const wxString& error_code_msg = wxString::Format("[%S %S]", error_code, show_time); + m_error_code_label->SetMaxSize(wxSize(FromDIP(300), -1)); + m_error_code_label->SetMinSize(wxSize(FromDIP(300), -1)); + m_error_code_label->SetLabelText(error_code_msg); + + /* error message*/ + m_error_msg_label->SetMaxSize(wxSize(FromDIP(300), -1)); + m_error_msg_label->SetMinSize(wxSize(FromDIP(300), -1)); + m_error_msg_label->SetLabelText(text); + + /* update layout*/ + { + m_scroll_area->Layout(); + auto text_size = m_error_msg_label->GetBestSize(); + if (text_size.y < FromDIP(360)) + { + if (!image_url.empty()) + { + m_scroll_area->SetMinSize(wxSize(FromDIP(320), text_size.y + FromDIP(220))); + } + else + { + m_scroll_area->SetMinSize(wxSize(FromDIP(320), text_size.y + FromDIP(50))); + } + } + else + { + m_scroll_area->SetMinSize(wxSize(FromDIP(320), FromDIP(340))); + } + + Layout(); + Fit(); + } +}; + +void DeviceErrorDialog::on_button_click(ActionButton btn_id) +{ + switch (btn_id) { + case DeviceErrorDialog::RESUME_PRINTING: { + m_obj->command_hms_resume(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::RESUME_PRINTING_DEFECTS: { + m_obj->command_hms_resume(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::RESUME_PRINTING_PROBELM_SOLVED: { + m_obj->command_hms_resume(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::STOP_PRINTING: { + m_obj->command_hms_stop(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::CHECK_ASSISTANT: { + wxGetApp().mainframe->m_monitor->jump_to_HMS(); // go to assistant page + break; + } + case DeviceErrorDialog::FILAMENT_EXTRUDED: { + m_obj->command_ams_control("done"); + break; + } + case DeviceErrorDialog::RETRY_FILAMENT_EXTRUDED: { + m_obj->command_ams_control("resume"); + return;// do not hide the dialogs + } + case DeviceErrorDialog::CONTINUE: { + m_obj->command_ams_control("resume"); + break; + } + case DeviceErrorDialog::LOAD_VIRTUAL_TRAY: { + //m_ams_control->SwitchAms(std::to_string(VIRTUAL_TRAY_MAIN_ID)); + //on_ams_load_curr(); + break;/*AP, unknown what it is*/ + } + case DeviceErrorDialog::OK_BUTTON: { + m_obj->command_clean_print_error(m_obj->subtask_id_, m_error_code); + break;/*do nothing*/ + } + case DeviceErrorDialog::FILAMENT_LOAD_RESUME: { + m_obj->command_hms_resume(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::JUMP_TO_LIVEVIEW: { + Slic3r::GUI::wxGetApp().mainframe->jump_to_monitor(); + Slic3r::GUI::wxGetApp().mainframe->m_monitor->jump_to_LiveView(); + break; + } + case DeviceErrorDialog::NO_REMINDER_NEXT_TIME: { + m_obj->command_hms_idle_ignore(std::to_string(m_error_code), 0); /*the type is 0, supported by AP*/ + break; + } + case DeviceErrorDialog::IGNORE_NO_REMINDER_NEXT_TIME: { + m_obj->command_hms_ignore(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::IGNORE_RESUME: { + m_obj->command_hms_ignore(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::PROBLEM_SOLVED_RESUME: { + m_obj->command_hms_resume(std::to_string(m_error_code), m_obj->job_id_); + break; + } + case DeviceErrorDialog::STOP_BUZZER: { + m_obj->command_stop_buzzer(); + break; + } + case DeviceErrorDialog::RETRY_PROBLEM_SOLVED: { + m_obj->command_ams_control("resume"); + break; + } + case DeviceErrorDialog::STOP_DRYING: { + m_obj->command_ams_drying_stop(); + break; + } + case DeviceErrorDialog::ERROR_BUTTON_COUNT: break; + default: break; + } + + Hide(); +} + +} +} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/DeviceErrorDialog.hpp b/src/slic3r/GUI/DeviceErrorDialog.hpp new file mode 100644 index 0000000000..2691e50953 --- /dev/null +++ b/src/slic3r/GUI/DeviceErrorDialog.hpp @@ -0,0 +1,88 @@ +#pragma once + +#include +#include + +#include "GUI_Utils.hpp" +#include "Widgets/StateColor.hpp" + +class Label; +class Button; + +namespace Slic3r { + +class MachineObject;//Previous definitions + +namespace GUI { + +class DeviceErrorDialog : public DPIDialog +{ +public: + enum ActionButton : int { + RESUME_PRINTING = 2, + RESUME_PRINTING_DEFECTS = 3, + RESUME_PRINTING_PROBELM_SOLVED = 4, + STOP_PRINTING = 5, + CHECK_ASSISTANT = 6, + FILAMENT_EXTRUDED = 7, + RETRY_FILAMENT_EXTRUDED = 8, + CONTINUE = 9, + LOAD_VIRTUAL_TRAY = 10, + OK_BUTTON = 11, + FILAMENT_LOAD_RESUME = 12, + JUMP_TO_LIVEVIEW, + + NO_REMINDER_NEXT_TIME = 23, + IGNORE_NO_REMINDER_NEXT_TIME = 25, + //LOAD_FILAMENT = 26*/ + IGNORE_RESUME = 27, + PROBLEM_SOLVED_RESUME = 28, + STOP_BUZZER = 29, + + RETRY_PROBLEM_SOLVED = 34, + STOP_DRYING = 35, + + ERROR_BUTTON_COUNT + }; + +public: + DeviceErrorDialog(MachineObject* obj, + wxWindow* parent, + wxWindowID id = wxID_ANY, + const wxString& title = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxCLOSE_BOX | wxCAPTION); + ~DeviceErrorDialog(); + +public: + void show_error_code(int error_code); + +protected: + void init_button_list(); + void init_button(ActionButton style, wxString buton_text); + + void update_contents(const wxString& text, const wxString& error_code,const wxString& image_url, const std::vector& btns); + + void on_button_click(ActionButton btn_id); + void on_webrequest_state(wxWebRequestEvent& evt); + void on_dpi_changed(const wxRect& suggested_rect); + +private: + MachineObject* m_obj; + + int m_error_code; + std::unordered_set m_used_button; + + wxWebRequest web_request; + wxStaticBitmap* m_error_picture; + Label* m_error_msg_label{ nullptr }; + Label* m_error_code_label{ nullptr }; + wxBoxSizer* m_sizer_main; + wxBoxSizer* m_sizer_button; + wxScrolledWindow* m_scroll_area{ nullptr }; + + std::map m_button_list; + StateColor btn_bg_white; +}; +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index 04676b741a..8ca8489b95 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -6,6 +6,7 @@ #include "GUI_App.hpp" #include "MsgDialog.hpp" +#include "DeviceErrorDialog.hpp" #include "Plater.hpp" #include "GUI_App.hpp" #include "ReleaseNote.hpp" @@ -777,6 +778,10 @@ MachineObject::~MachineObject() it->second->trayList.clear(); } amsList.clear(); + + while (!m_command_error_code_dlgs.empty()) { + delete *m_command_error_code_dlgs.begin();/*element will auto remove from m_command_error_code_dlgs on deleted*/ + } } bool MachineObject::check_valid_ip() @@ -1946,6 +1951,24 @@ int MachineObject::command_clean_print_error(std::string subtask_id, int print_e return this->publish_json(j.dump()); } +int MachineObject::command_clean_print_error_uiop(int print_error) +{ + json j; + j["system"]["command"] = "uiop"; + j["system"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["system"]["name"] = "print_error"; + j["system"]["action"] = "close"; + j["system"]["source"] = 1;// 0-Mushu 1-Studio + j["system"]["type"] = "dialog"; + + // the error to be cleaned + char buf[32]; + ::sprintf(buf, "%08X", print_error); + j["system"]["err"] = std::string(buf); + + return this->publish_json(j); +} + int MachineObject::command_upgrade_confirm() { BOOST_LOG_TRIVIAL(info) << "command_upgrade_confirm"; @@ -2348,6 +2371,13 @@ int MachineObject::command_ams_control(std::string action) return -1; } +int MachineObject::command_ams_drying_stop() +{ + json j; + j["print"]["command"] = "auto_stop_ams_dry"; + j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + return this->publish_json(j); +} int MachineObject::command_set_chamber_light(LIGHT_EFFECT effect, int on_time, int off_time, int loops, int interval) { @@ -3826,6 +3856,15 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ } } } + + if (!key_field_only) + { + if (jj.contains("command") && jj.contains("err_code") && jj.contains("result")) + { + if (jj["err_code"].is_number()) { add_command_error_code_dlg(jj["err_code"].get());} + } + } + if (jj["command"].get() == "push_status") { m_push_count++; last_push_time = last_update_time; @@ -5592,6 +5631,12 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_ upgrade_display_hold_count = HOLD_COUNT_MAX; BOOST_LOG_TRIVIAL(info) << "ack of upgrade_confirm"; } + + if (j["upgrade"].contains("err_code")) { + if (j["upgrade"]["err_code"].is_number()) { + add_command_error_code_dlg(j["upgrade"]["err_code"].get()); + } + } } } } @@ -7033,6 +7078,37 @@ wxString MachineObject::get_nozzle_replace_url() const return "https://wiki.bambulab.com/en/h2/maintenance/replace-hotend"; } +std::string MachineObject::get_error_code_str(int error_code) +{ + if (error_code < 0) { return std::string();} + + char buf[32]; + ::sprintf(buf, "%08X", error_code); + std::string print_error_str = std::string(buf); + if (print_error_str.size() > 4) { print_error_str.insert(4, "-"); } + return print_error_str; +} + +void MachineObject::add_command_error_code_dlg(int command_err) +{ + if (command_err > 0 && !Slic3r::GUI::wxGetApp().get_hms_query()->is_internal_error(this, command_err)) + { + GUI::wxGetApp().CallAfter([this, command_err, token = std::weak_ptr(m_token)] + { + if (token.expired()) { return;} + GUI::DeviceErrorDialog* device_error_dialog = new GUI::DeviceErrorDialog(this, (wxWindow*)GUI::wxGetApp().mainframe); + device_error_dialog->Bind(wxEVT_DESTROY, [this, token = std::weak_ptr(m_token)](auto& event) + { + if (!token.expired()) { m_command_error_code_dlgs.erase((GUI::DeviceErrorDialog*)event.GetEventObject());} + event.Skip(); + }); + + device_error_dialog->show_error_code(command_err); + m_command_error_code_dlgs.insert(device_error_dialog); + }); + }; +} + bool DeviceManager::EnableMultiMachine = false; bool DeviceManager::key_field_only = false; diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index 59924faab2..d01a0e2195 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include "nlohmann/json.hpp" @@ -74,6 +75,10 @@ using namespace nlohmann; namespace Slic3r { +namespace GUI { + class DeviceErrorDialog; // Previous definitions +} + struct BBLocalMachine; class SecondaryCheckDialog; enum PrinterArch { @@ -919,6 +924,12 @@ public: int hw_switch_state; bool is_system_printing(); int print_error; + static std::string get_error_code_str(int error_code); + std::string get_print_error_str() const { return MachineObject::get_error_code_str(this->print_error); } + + std::unordered_set m_command_error_code_dlgs; + void add_command_error_code_dlg(int command_err); + int curr_layer = 0; int total_layers = 0; bool is_support_layer_num { false }; @@ -1221,6 +1232,7 @@ public: int command_request_push_all(bool request_now = false); int command_pushing(std::string cmd); int command_clean_print_error(std::string task_id, int print_error); + int command_clean_print_error_uiop(int print_error); int command_set_printer_nozzle(std::string nozzle_type, float diameter); int command_set_printer_nozzle2(int id, std::string nozzle_type, float diameter); int command_get_access_code(); @@ -1272,6 +1284,9 @@ public: int command_ams_refresh_rfid(std::string tray_id); int command_ams_refresh_rfid2(int ams_id, int slot_id); int command_ams_control(std::string action); + + int command_ams_drying_stop(); + int command_set_chamber_light(LIGHT_EFFECT effect, int on_time = 500, int off_time = 500, int loops = 1, int interval = 1000); int command_set_chamber_light2(LIGHT_EFFECT effect, int on_time = 500, int off_time = 500, int loops = 1, int interval = 1000); int command_set_work_light(LIGHT_EFFECT effect, int on_time = 500, int off_time = 500, int loops = 1, int interval = 1000); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index fbee22caa0..2a3dc7c866 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -3590,7 +3590,9 @@ void MainFrame::jump_to_monitor(std::string dev_id) if(!m_monitor) return; m_tabpanel->SetSelection(tpMonitor); - ((MonitorPanel*)m_monitor)->select_machine(dev_id); + if (!dev_id.empty()) { + ((MonitorPanel*)m_monitor)->select_machine(dev_id); + } } void MainFrame::jump_to_multipage() diff --git a/src/slic3r/GUI/Monitor.cpp b/src/slic3r/GUI/Monitor.cpp index 523648c610..63da6f5a26 100644 --- a/src/slic3r/GUI/Monitor.cpp +++ b/src/slic3r/GUI/Monitor.cpp @@ -507,7 +507,7 @@ std::string MonitorPanel::get_string_from_tab(PrinterTab tab) return ""; } -void MonitorPanel::jump_to_HMS(wxCommandEvent& e) +void MonitorPanel::jump_to_HMS() { if (!this->IsShown()) return; @@ -516,6 +516,18 @@ void MonitorPanel::jump_to_HMS(wxCommandEvent& e) m_tabpanel->SetSelection(PT_HMS); } +void MonitorPanel::jump_to_LiveView() +{ + if (!this->IsShown()) { return; } + + auto page = m_tabpanel->GetCurrentPage(); + if (page && page != m_hms_panel) + { + m_tabpanel->SetSelection(PT_STATUS); + } + + m_status_info_panel->get_media_play_ctrl()->jump_to_play(); +} } // GUI } // Slic3r diff --git a/src/slic3r/GUI/Monitor.hpp b/src/slic3r/GUI/Monitor.hpp index 7d2846f227..a7f7126534 100644 --- a/src/slic3r/GUI/Monitor.hpp +++ b/src/slic3r/GUI/Monitor.hpp @@ -154,7 +154,9 @@ public: void stop_update() {update_flag = false;}; void start_update() {update_flag = true;}; - void jump_to_HMS(wxCommandEvent& e); + + void jump_to_HMS(); + void jump_to_LiveView(); }; diff --git a/src/slic3r/GUI/ReleaseNote.cpp b/src/slic3r/GUI/ReleaseNote.cpp index ef2898a308..126ab9de3e 100644 --- a/src/slic3r/GUI/ReleaseNote.cpp +++ b/src/slic3r/GUI/ReleaseNote.cpp @@ -1123,6 +1123,7 @@ void PrintErrorDialog::init_button_list() init_button(PROBLEM_SOLVED_RESUME, _L("Problem Solved and Resume")); init_button(STOP_BUZZER, _L("Stop Buzzer")); init_button(RETRY_PROBLEM_SOLVED, _L("Retry (problem solved)")); + init_button(STOP_DRYING, _L("Stop Drying")); } PrintErrorDialog::~PrintErrorDialog() diff --git a/src/slic3r/GUI/ReleaseNote.hpp b/src/slic3r/GUI/ReleaseNote.hpp index d2f3f4758e..e9458338f5 100644 --- a/src/slic3r/GUI/ReleaseNote.hpp +++ b/src/slic3r/GUI/ReleaseNote.hpp @@ -188,6 +188,7 @@ public: STOP_BUZZER = 29, RETRY_PROBLEM_SOLVED = 34, + STOP_DRYING = 35, ERROR_BUTTON_COUNT }; diff --git a/src/slic3r/GUI/StatusPanel.cpp b/src/slic3r/GUI/StatusPanel.cpp index 2fdb906cec..1902eef463 100644 --- a/src/slic3r/GUI/StatusPanel.cpp +++ b/src/slic3r/GUI/StatusPanel.cpp @@ -2724,6 +2724,12 @@ void StatusPanel::show_error_message(MachineObject *obj, bool is_exist, wxString m_print_error_dlg->update_title_style(_L("Error"), used_button, this); m_print_error_dlg->update_text_image(msg, print_error_str, image_url); + m_print_error_dlg->Bind(wxEVT_CLOSE_WINDOW, [this, dev_id](wxCloseEvent& e) + { + MachineObject *the_obj = wxGetApp().getDeviceManager()->get_my_machine(dev_id); + if (the_obj) { the_obj->command_clean_print_error_uiop(the_obj->print_error); } + e.Skip(); + }); m_print_error_dlg->on_show(); } else { @@ -2760,7 +2766,17 @@ void StatusPanel::show_error_message(MachineObject *obj, bool is_exist, wxString m_print_error_dlg_no_action->update_text(error_code_msg); m_print_error_dlg_no_action->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this, dev_id](wxCommandEvent &e) { MachineObject *the_obj = wxGetApp().getDeviceManager()->get_my_machine(dev_id); - if (the_obj) { the_obj->command_clean_print_error(the_obj->subtask_id_, the_obj->print_error); } + if (the_obj) { + the_obj->command_clean_print_error(the_obj->subtask_id_, the_obj->print_error); + the_obj->command_clean_print_error_uiop(the_obj->print_error); + } + }); + + m_print_error_dlg_no_action->Bind(wxEVT_CLOSE_WINDOW, [this, dev_id](wxCloseEvent& e) + { + MachineObject *the_obj = wxGetApp().getDeviceManager()->get_my_machine(dev_id); + if (the_obj) { the_obj->command_clean_print_error_uiop(the_obj->print_error); } + e.Skip(); }); m_print_error_dlg_no_action->Bind(EVT_SECONDARY_CHECK_RETRY, [this](wxCommandEvent& e) { @@ -4678,7 +4694,7 @@ void StatusPanel::on_print_error_dlg_btn_clicked(wxCommandEvent& event) break; } case Slic3r::GUI::PrintErrorDialog::CHECK_ASSISTANT: { - wxGetApp().mainframe->m_monitor->jump_to_HMS(event); // go to assistant page + wxGetApp().mainframe->m_monitor->jump_to_HMS(); // go to assistant page break; } case Slic3r::GUI::PrintErrorDialog::FILAMENT_EXTRUDED: { @@ -4734,6 +4750,10 @@ void StatusPanel::on_print_error_dlg_btn_clicked(wxCommandEvent& event) obj->command_ams_control("resume"); break; } + case Slic3r::GUI::PrintErrorDialog::STOP_DRYING: { + obj->command_ams_drying_stop(); + break; + } case Slic3r::GUI::PrintErrorDialog::ERROR_BUTTON_COUNT: break; default: break; }