OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::Moonraker Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/Utils/Moonraker.hpp>

Inheritance diagram for Slic3r::Moonraker:
Collaboration diagram for Slic3r::Moonraker:

Public Types

typedef Http::ProgressFn ProgressFn
typedef std::function< void(wxString)> ErrorFn
typedef std::function< void(wxString, wxString)> InfoFn

Public Member Functions

 Moonraker (DynamicPrintConfig *config)
 ~Moonraker () override=default
const char * get_name () const override
bool test (wxString &curl_msg) const override
wxString get_test_ok_msg () const override
wxString get_test_failed_msg (wxString &msg) const override
bool upload (PrintHostUpload upload_data, ProgressFn progress_fn, ErrorFn error_fn, InfoFn info_fn) const override
bool has_auto_discovery () const override
bool can_test () const override
PrintHostPostUploadActions get_post_upload_actions () const override
std::string get_host () const override
bool get_storage (wxArrayString &storage_path, wxArrayString &storage_name) const override
const std::string & get_apikey () const
const std::string & get_cafile () const
virtual bool supports_multiple_printers () const
virtual std::string get_sn () const
virtual bool get_groups (wxArrayString &) const
virtual bool get_printers (wxArrayString &) const
virtual bool is_cloud () const
virtual bool is_logged_in () const
virtual void log_out () const
virtual bool get_login_url (wxString &auth_url) const

Static Public Member Functions

static PrintHost * get_print_host (DynamicPrintConfig *config)
static std::string get_print_host_webui (DynamicPrintConfig *config)
static int get_err_code_from_body (const std::string &body)

Protected Member Functions

void set_auth (Http &http) const
std::string make_url (const std::string &path) const
bool start_print (wxString &error_msg, const std::string &filename) const
virtual wxString format_error (const std::string &body, const std::string &error, unsigned status) const

Static Protected Member Functions

static wxString timed_out_message ()

Protected Attributes

std::string m_host
std::string m_apikey
std::string m_cafile
bool m_ssl_revoke_best_effort

Detailed Description

Member Typedef Documentation

◆ ErrorFn

typedef std::function<void(wxString )> Slic3r::PrintHost::ErrorFn
inherited

◆ InfoFn

typedef std::function<void(wxString , wxString )> Slic3r::PrintHost::InfoFn
inherited

◆ ProgressFn

Constructor & Destructor Documentation

◆ Moonraker()

Slic3r::Moonraker::Moonraker ( DynamicPrintConfig * config)
25 : m_host(config->opt_string("print_host"))
26 , m_apikey(config->opt_string("printhost_apikey"))
27 , m_cafile(config->opt_string("printhost_cafile"))
28 , m_ssl_revoke_best_effort(config->opt_bool("printhost_ssl_ignore_revoke"))
29{}
std::string m_cafile
Definition Moonraker.hpp:57
std::string m_host
Definition Moonraker.hpp:55
bool m_ssl_revoke_best_effort
Definition Moonraker.hpp:58
std::string m_apikey
Definition Moonraker.hpp:56

References m_apikey, m_cafile, m_host, and m_ssl_revoke_best_effort.

◆ ~Moonraker()

Slic3r::Moonraker::~Moonraker ( )
overridedefault

Member Function Documentation

◆ can_test()

bool Slic3r::Moonraker::can_test ( ) const
inlineoverridevirtual

Implements Slic3r::PrintHost.

47{ return true; }

◆ format_error()

wxString Slic3r::PrintHost::format_error ( const std::string & body,
const std::string & error,
unsigned status ) const
protectedvirtualinherited
203{
204 if (status != 0) {
205 const std::string reason = moonraker_error_reason(body);
206 auto wxbody = wxString::FromUTF8(reason.empty() ? body : reason);
207 return wxString::Format("HTTP %u: %s", status, wxbody);
208 } else {
209 if (error.find("curl:Timeout was reached") != std::string::npos) {
210 return timed_out_message();
211 }else if(error.find("curl:Couldn't resolve host name")!= std::string::npos){
212 return _L("The Hostname/IP/URL could not be parsed, please check it and try again.");
213 } else if (error.find("Connection was reset") != std::string::npos){
214 return _L("File/data transfer interrupted. Please check the printer and network, then try it again.");
215 }
216 else {
217 return wxString::FromUTF8(error.data());
218 }
219 }
220}
#define _L(s)
Definition OBJ.cpp:34
static wxString timed_out_message()
Definition PrintHost.cpp:222
std::string moonraker_error_reason(const std::string &body)
Definition PrintHost.cpp:137

References _L, and timed_out_message().

Referenced by Slic3r::Duet::connect(), Slic3r::UltiMaker::connect(), Slic3r::SimplyPrint::do_chunk_upload(), Slic3r::SimplyPrint::do_temp_upload(), Slic3r::ElegooLink::elegoo_cc2_test(), Slic3r::ElegooLink::elegoo_test(), Slic3r::PrusaLink::post_inner(), Slic3r::PrusaLink::put_inner(), Slic3r::Flashforge::request_local_api_json(), Slic3r::Duet::start_print(), Slic3r::Moonraker::start_print(), Slic3r::UltiMaker::start_print(), Slic3r::AstroBox::test(), Slic3r::CrealityPrint::test(), Slic3r::ESP3D::test(), Slic3r::FlashAir::test(), Slic3r::Moonraker::test(), Slic3r::Obico::test(), Slic3r::OctoPrint::test(), Slic3r::PrusaLink::test(), Slic3r::Repetier::test(), Slic3r::UltiMaker::test(), Slic3r::PrusaLink::test_with_method_check(), Slic3r::AstroBox::upload(), Slic3r::C3DPrinterOS::upload(), Slic3r::CrealityPrint::upload(), Slic3r::Duet::upload(), Slic3r::ESP3D::upload(), Slic3r::FlashAir::upload(), Slic3r::MKS::upload(), Slic3r::Moonraker::upload(), Slic3r::Obico::upload(), Slic3r::Repetier::upload(), Slic3r::UltiMaker::upload(), Slic3r::OctoPrint::upload_inner_with_host(), Slic3r::Flashforge::upload_local_api(), Slic3r::ElegooLink::uploadPart(), and Slic3r::ElegooLink::uploadPartCC2().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_apikey()

const std::string & Slic3r::Moonraker::get_apikey ( ) const
inline
51{ return m_apikey; }

References m_apikey.

◆ get_cafile()

const std::string & Slic3r::Moonraker::get_cafile ( ) const
inline
52{ return m_cafile; }

References m_cafile.

◆ get_err_code_from_body()

int Slic3r::PrintHost::get_err_code_from_body ( const std::string & body)
staticinherited
189{
190 boost::property_tree::ptree root;
191 std::istringstream iss(body);
192 try {
193 boost::property_tree::read_json(iss, root);
194 } catch (const std::exception &ex) {
195 BOOST_LOG_TRIVIAL(error) << "PrintHost: response is not valid JSON: " << ex.what();
196 return -1;
197 }
198
199 return root.get<int>("err", 0);
200}

Referenced by Slic3r::Duet::connect(), Slic3r::UltiMaker::connect(), Slic3r::Duet::upload(), Slic3r::MKS::upload(), and Slic3r::UltiMaker::upload().

Here is the caller graph for this function:

◆ get_groups()

virtual bool Slic3r::PrintHost::get_groups ( wxArrayString & ) const
inlinevirtualinherited

Reimplemented in Slic3r::Repetier.

84{ return false; }

◆ get_host()

std::string Slic3r::Moonraker::get_host ( ) const
inlineoverridevirtual

Implements Slic3r::PrintHost.

49{ return m_host; }

References m_host.

◆ get_login_url()

virtual bool Slic3r::PrintHost::get_login_url ( wxString & auth_url) const
inlinevirtualinherited

Reimplemented in Slic3r::Obico.

99{ return false; }

Referenced by Slic3r::GUI::PrinterCloudAuthDialog::PrinterCloudAuthDialog().

Here is the caller graph for this function:

◆ get_name()

const char * Slic3r::Moonraker::get_name ( ) const
overridevirtual

Implements Slic3r::PrintHost.

31{ return "Moonraker"; }

Referenced by get_storage(), start_print(), test(), and upload().

Here is the caller graph for this function:

◆ get_post_upload_actions()

PrintHostPostUploadActions Slic3r::Moonraker::get_post_upload_actions ( ) const
inlineoverridevirtual

Implements Slic3r::PrintHost.

@ StartPrint
Definition PrintHost.hpp:25

References Slic3r::StartPrint.

◆ get_print_host()

PrintHost * Slic3r::PrintHost::get_print_host ( DynamicPrintConfig * config)
staticinherited
59{
61
62 {
63 const auto opt = config->option<ConfigOptionEnum<PrinterTechnology>>("printer_technology");
64 if (opt != nullptr) {
65 tech = opt->value;
66 }
67 }
68
69 if (tech == ptFFF) {
70 const auto opt = config->option<ConfigOptionEnum<PrintHostType>>("host_type");
71 const auto host_type = opt != nullptr ? opt->value : htOctoPrint;
72
73 switch (host_type) {
74 case htOctoPrint: return new OctoPrint(config);
75 case htDuet: return new Duet(config);
76 case htUltiMaker: return new UltiMaker(config);
77 case htFlashAir: return new FlashAir(config);
78 case htAstroBox: return new AstroBox(config);
79 case htRepetier: return new Repetier(config);
80 case htPrusaLink: return new PrusaLink(config);
81 case htPrusaConnect: return new PrusaConnect(config);
82 case htMKS: return new MKS(config);
83 case htESP3D: return new ESP3D(config);
84 case htCrealityPrint: return new CrealityPrint(config);
85 case htObico: return new Obico(config);
86 case htFlashforge: return new Flashforge(config);
87 case htSimplyPrint: return new SimplyPrint(config);
88 case htElegooLink: return new ElegooLink(config);
89 case ht3DPrinterOS: return new C3DPrinterOS(config);
90 case htMoonraker: return new Moonraker(config);
91 default: return nullptr;
92 }
93 } else {
94 return new SL1Host(config);
95 }
96}
PrinterTechnology
Definition Config.hpp:229
@ ptFFF
Definition Config.hpp:231
@ htSimplyPrint
Definition PrintConfig.hpp:119
@ htMoonraker
Definition PrintConfig.hpp:119
@ htElegooLink
Definition PrintConfig.hpp:119
@ htCrealityPrint
Definition PrintConfig.hpp:119
@ ht3DPrinterOS
Definition PrintConfig.hpp:119
@ htPrusaLink
Definition PrintConfig.hpp:119
@ htRepetier
Definition PrintConfig.hpp:119
@ htMKS
Definition PrintConfig.hpp:119
@ htPrusaConnect
Definition PrintConfig.hpp:119
@ htDuet
Definition PrintConfig.hpp:119
@ htUltiMaker
Definition PrintConfig.hpp:119
@ htObico
Definition PrintConfig.hpp:119
@ htOctoPrint
Definition PrintConfig.hpp:119
@ htFlashforge
Definition PrintConfig.hpp:119
@ htFlashAir
Definition PrintConfig.hpp:119
@ htAstroBox
Definition PrintConfig.hpp:119
@ htESP3D
Definition PrintConfig.hpp:119
ConfigOptionEnum< PrinterTechnology >
Definition PrintConfig.hpp:2358

References Slic3r::ht3DPrinterOS, Slic3r::htAstroBox, Slic3r::htCrealityPrint, Slic3r::htDuet, Slic3r::htElegooLink, Slic3r::htESP3D, Slic3r::htFlashAir, Slic3r::htFlashforge, Slic3r::htMKS, Slic3r::htMoonraker, Slic3r::htObico, Slic3r::htOctoPrint, Slic3r::htPrusaConnect, Slic3r::htPrusaLink, Slic3r::htRepetier, Slic3r::htSimplyPrint, Slic3r::htUltiMaker, Slic3r::ConfigBase::option(), and Slic3r::ptFFF.

Referenced by Slic3r::GUI::PhysicalPrinterDialog::build_printhost_settings(), Slic3r::GUI::anonymous_namespace{PrinterWebViewHandler.cpp}::ElegooPrinterWebViewHandler::handle_get_sn_request(), Slic3r::GUI::anonymous_namespace{PrinterWebViewHandler.cpp}::ElegooPrinterWebViewHandler::handle_upload_request(), Slic3r::GUI::PhysicalPrinterDialog::update_printers(), and Slic3r::GUI::PhysicalPrinterDialog::update_printhost_buttons().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_print_host_webui()

std::string Slic3r::PrintHost::get_print_host_webui ( DynamicPrintConfig * config)
staticinherited
99{
100 if (config == nullptr)
101 return {};
102
103 std::string webui_url;
104 const auto* host_type_opt = config->option<ConfigOptionEnum<PrintHostType>>("host_type");
105 const auto host_type = host_type_opt != nullptr ? host_type_opt->value : htOctoPrint;
106
107 switch (host_type) {
108 case htElegooLink: {
109 webui_url = ElegooLink::get_print_host_webui(config);
110 break;
111 }
112 default: break;
113 }
114
115 if (webui_url.empty()) {
116 webui_url = config->opt_string("print_host_webui");
117 if (webui_url.empty())
118 webui_url = config->opt_string("print_host");
119 if (webui_url.empty())
120 return webui_url;
121 }
122
123 const bool has_http_scheme = boost::algorithm::istarts_with(webui_url, "http");
124 const bool has_file_scheme = boost::algorithm::istarts_with(webui_url, "file:");
125
126 if (!has_http_scheme && !has_file_scheme)
127 webui_url = "http://" + webui_url;
128
129 return webui_url;
130}

References Slic3r::ElegooLink::get_print_host_webui(), Slic3r::htElegooLink, Slic3r::htOctoPrint, Slic3r::DynamicConfig::opt_string(), Slic3r::ConfigBase::option(), and Slic3r::ConfigOptionSingle< T >::value.

Referenced by Slic3r::GUI::MainFrame::load_printer_url(), Slic3r::GUI::Plater::priv::on_tab_selection_changing(), and Slic3r::GUI::Sidebar::update_all_preset_comboboxes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_printers()

virtual bool Slic3r::PrintHost::get_printers ( wxArrayString & ) const
inlinevirtualinherited

Reimplemented in Slic3r::Obico, and Slic3r::Repetier.

85{ return false; }

◆ get_sn()

virtual std::string Slic3r::PrintHost::get_sn ( ) const
inlinevirtualinherited

Get the serial number for connecting to the printer. For Elegoo CC2, the device details connection to the printer requires the serial number. Other print hosts do not need to implement this interface, and it returns an empty string by default.

Reimplemented in Slic3r::ElegooLink.

80{ return ""; }

◆ get_storage()

bool Slic3r::Moonraker::get_storage ( wxArrayString & storage_path,
wxArrayString & storage_name ) const
overridevirtual

Reimplemented from Slic3r::PrintHost.

115{
116 //ORCA: GET /server/files/roots enumerates Moonraker's storage roots (default "gcodes" plus any
117 // configured extras like "config", "logs", "timelapse"). Only roots with permissions
118 // including "rw" or "rwd" can receive uploads; we filter to those so the UI dropdown only
119 // offers usable destinations. The base class returns false (no per-host storage); returning
120 // true here populates the storage picker in PrintHostDialogs's send-to-print dialog.
121 // Failures (404 — older Moonraker, or a buddy-fork that doesn't implement the endpoint)
122 // gracefully degrade to false so upload() falls back to the hardcoded "gcodes" default.
123 const char *name = get_name();
124 bool got_any = false;
125 auto url = make_url("server/files/roots");
126
127 BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Enumerating storage roots at: %2%") % name % url;
128
129 auto http = Http::get(std::move(url));
130 set_auth(http);
131 http.on_error([&](std::string body, std::string error, unsigned status) {
132 //ORCA: /server/files/roots is optional in the Moonraker spec and absent on older versions
133 // and slimmer shims (e.g. Prusa-Firmware-Buddy 0.8.x prusalink-shim returns 501). A
134 // missing endpoint here is benign — upload() silently falls back to the hardcoded
135 // "gcodes" root — so don't pollute the log at warning level for it. Other HTTP
136 // errors still warn.
137 if (status == 404 || status == 501) {
138 BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: /server/files/roots not implemented (HTTP %2%); upload() will fall back to the \"gcodes\" root.")
139 % name % status;
140 } else {
141 BOOST_LOG_TRIVIAL(warning) << boost::format("%1%: Could not enumerate roots: %2%, HTTP %3%, body: `%4%`")
142 % name % error % status % body;
143 }
144 })
145 .on_complete([&](std::string body, unsigned) {
146 BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: /server/files/roots body: %2%") % name % body;
147 try {
148 std::stringstream ss(body);
149 pt::ptree ptree;
150 pt::read_json(ss, ptree);
151 const auto result_node = ptree.get_child_optional("result");
152 if (!result_node)
153 return;
154 for (const auto &child : *result_node) {
155 const std::string &root = child.second.get<std::string>("name", "");
156 const std::string &perms = child.second.get<std::string>("permissions", "");
157 if (root.empty() || perms.find('w') == std::string::npos)
158 continue;
159 storage_path.Add(wxString::FromUTF8(root));
160 storage_name.Add(wxString::FromUTF8(root));
161 got_any = true;
162 }
163 } catch (const std::exception &ex) {
164 BOOST_LOG_TRIVIAL(warning) << boost::format("%1%: Could not parse roots: %2%") % name % ex.what();
165 }
166 })
167#ifdef WIN32
168 .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
169#endif
170 .perform_sync();
171
172 return got_any;
173}
static Http get(std::string url)
Definition Http.cpp:886
void set_auth(Http &http) const
Definition Moonraker.cpp:53
const char * get_name() const override
Definition Moonraker.cpp:31
std::string make_url(const std::string &path) const
Definition Moonraker.cpp:43
boost::filesystem::path storage_path()
Definition InstanceID.cpp:100
@ http
Definition IPrinterAgent.hpp:64

References Slic3r::Http::get(), get_name(), Slic3r::http, m_ssl_revoke_best_effort, make_url(), and set_auth().

Here is the call graph for this function:

◆ get_test_failed_msg()

wxString Slic3r::Moonraker::get_test_failed_msg ( wxString & msg) const
overridevirtual

Implements Slic3r::PrintHost.

39{
40 return GUI::format_wxstr("%s: %s", _L("Could not connect to Moonraker"), msg);
41}
wxString format_wxstr(const char *fmt, TArgs &&... args)
Definition format.hpp:22

References _L, and Slic3r::GUI::format_wxstr().

Here is the call graph for this function:

◆ get_test_ok_msg()

wxString Slic3r::Moonraker::get_test_ok_msg ( ) const
overridevirtual

Implements Slic3r::PrintHost.

34{
35 return _(L("Connection to Moonraker is working correctly."));
36}
#define _(s)
Definition 3mf.cpp:306
#define L(s)
Definition ExtrusionEntity.cpp:25

References _, and L.

◆ has_auto_discovery()

bool Slic3r::Moonraker::has_auto_discovery ( ) const
inlineoverridevirtual

Implements Slic3r::PrintHost.

46{ return false; }

◆ is_cloud()

virtual bool Slic3r::PrintHost::is_cloud ( ) const
inlinevirtualinherited

Reimplemented in Slic3r::C3DPrinterOS, Slic3r::Obico, and Slic3r::SimplyPrint.

96{ return false; }

◆ is_logged_in()

virtual bool Slic3r::PrintHost::is_logged_in ( ) const
inlinevirtualinherited

Reimplemented in Slic3r::C3DPrinterOS, and Slic3r::SimplyPrint.

97{ return false; }

◆ log_out()

virtual void Slic3r::PrintHost::log_out ( ) const
inlinevirtualinherited

Reimplemented in Slic3r::C3DPrinterOS, and Slic3r::SimplyPrint.

98{}

◆ make_url()

std::string Slic3r::Moonraker::make_url ( const std::string & path) const
protected
44{
45 if (m_host.find("http://") == 0 || m_host.find("https://") == 0) {
46 if (m_host.back() == '/')
47 return (boost::format("%1%%2%") % m_host % path).str();
48 return (boost::format("%1%/%2%") % m_host % path).str();
49 }
50 return (boost::format("http://%1%/%2%") % m_host % path).str();
51}

References m_host.

Referenced by get_storage(), start_print(), test(), and upload().

Here is the caller graph for this function:

◆ set_auth()

void Slic3r::Moonraker::set_auth ( Http & http) const
protected
54{
55 if (!m_apikey.empty())
56 http.header("X-Api-Key", m_apikey);
57 if (!m_cafile.empty())
58 http.ca_file(m_cafile);
59}

References Slic3r::http, m_apikey, and m_cafile.

Referenced by get_storage(), start_print(), test(), and upload().

Here is the caller graph for this function:

◆ start_print()

bool Slic3r::Moonraker::start_print ( wxString & error_msg,
const std::string & filename ) const
protected
176{
177 //ORCA: POST /printer/print/start with JSON body { "filename": "<name>.gcode" }.
178 // `filename` is the item.path /server/files/upload returned (the storage-relative
179 // path inside `root`, no leading slash, with extension), or the original filename
180 // when the reply had none. Build the body via property_tree so that special characters
181 // in the filename (quotes, backslashes) are properly escaped.
182 const char *name = get_name();
183 bool res = true;
184 auto url = make_url("printer/print/start");
185 pt::ptree body_tree;
186 body_tree.put("filename", filename);
187 std::ostringstream body_ss;
188 pt::write_json(body_ss, body_tree, /*pretty=*/false);
189 std::string body = body_ss.str();
190
191 BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Starting print of %2% at %3%") % name % filename % url;
192
193 auto http = Http::post(std::move(url));
194 set_auth(http);
195 http.header("Content-Type", "application/json")
196 .set_post_body(body)
197 .on_complete([&](std::string body, unsigned status) {
198 BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: print/start HTTP %2%: %3%") % name % status % body;
199 })
200 .on_error([&](std::string body, std::string error, unsigned status) {
201 BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error starting print at %2%: %3%, HTTP %4%, body: `%5%`")
202 % name % url % error % status % body;
203 res = false;
204 error_msg = format_error(body, error, status);
205 })
206#ifdef WIN32
207 .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
208#endif
209 .perform_sync();
210
211 return res;
212}
static Http post(std::string url)
Definition Http.cpp:891
virtual wxString format_error(const std::string &body, const std::string &error, unsigned status) const
Definition PrintHost.cpp:202

References Slic3r::PrintHost::format_error(), get_name(), Slic3r::http, m_ssl_revoke_best_effort, make_url(), Slic3r::Http::post(), and set_auth().

Referenced by upload().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ supports_multiple_printers()

virtual bool Slic3r::PrintHost::supports_multiple_printers ( ) const
inlinevirtualinherited

Reimplemented in Slic3r::Repetier.

73{ return false; }

◆ test()

bool Slic3r::Moonraker::test ( wxString & curl_msg) const
overridevirtual

Implements Slic3r::PrintHost.

62{
63 //ORCA: Moonraker's /server/info returns
64 // { "result": { "klippy_state": "ready|startup|shutdown|error|disconnected", ... } }
65 // We treat the connection as healthy as long as the envelope is valid and `klippy_state`
66 // is present — matching the OctoPrint/PrusaLink convention of "can I reach this host?".
67 // Klipper state (idle, error, etc.) is surfaced to the log but does not gate the test:
68 // buddy-fork firmwares legitimately report non-`ready` states at idle, and any real upload
69 // problem will surface a contextual error at upload() time anyway.
70 const char *name = get_name();
71 bool res = true;
72 auto url = make_url("server/info");
73
74 BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get server info at: %2%") % name % url;
75
76 auto http = Http::get(std::move(url));
78 http.on_error([&](std::string body, std::string error, unsigned status) {
79 BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting server info: %2%, HTTP %3%, body: `%4%`")
80 % name % error % status % body;
81 res = false;
82 msg = format_error(body, error, status);
83 })
84 .on_complete([&](std::string body, unsigned) {
85 BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: /server/info body: %2%") % name % body;
86 try {
87 std::stringstream ss(body);
88 pt::ptree ptree;
89 pt::read_json(ss, ptree);
90
91 const auto klippy_state = ptree.get_optional<std::string>("result.klippy_state");
92 if (!klippy_state) {
93 //ORCA: response wasn't shaped like a Moonraker /server/info reply — likely an OctoPrint
94 // or PrusaLink host the user mis-selected as Moonraker, or a totally different
95 // service. Treat as a connection failure with a clear hint.
96 res = false;
97 msg = _L("The host responded but it doesn't look like Moonraker (missing result.klippy_state).");
98 return;
99 }
100 BOOST_LOG_TRIVIAL(info) << boost::format("%1%: klippy_state = %2%") % name % (*klippy_state);
101 } catch (const std::exception &ex) {
102 res = false;
103 msg = GUI::format_wxstr(_L("Could not parse Moonraker server response: %s"), ex.what());
104 }
105 })
106#ifdef WIN32
107 .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
108#endif
109 .perform_sync();
110
111 return res;
112}

References _L, Slic3r::PrintHost::format_error(), Slic3r::GUI::format_wxstr(), Slic3r::Http::get(), get_name(), Slic3r::http, m_ssl_revoke_best_effort, make_url(), and set_auth().

Referenced by upload().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ timed_out_message()

wxString Slic3r::PrintHost::timed_out_message ( )
staticprotectedinherited
223{
224 return _L("Connection timed out. Please check if the printer and computer network are functioning properly, and confirm that they are on the same network.");
225}

References _L.

Referenced by format_error(), and Slic3r::CrealityPrint::start_print().

Here is the caller graph for this function:

◆ upload()

bool Slic3r::Moonraker::upload ( PrintHostUpload upload_data,
ProgressFn progress_fn,
ErrorFn error_fn,
InfoFn info_fn ) const
overridevirtual

Implements Slic3r::PrintHost.

215{
216 // POST /server/files/upload with `print=true` so Moonraker starts the print
217 // itself (issue #14945). It reports back in two fields: print_started when it
218 // began the print immediately, print_queued when it could not start it (Klippy
219 // not ready, or another print running) but put the job in its queue
220 // ([file_manager] queue_gcode_uploads). That covers the power-on case: a
221 // [power <device>] section with on_when_job_queued switches the printer on, and
222 // with [job_queue] load_on_startup the queue runs the job once Klippy is READY.
223 // Either flag means Moonraker owns the print and we must NOT issue our own
224 // /printer/print/start. When both are false (no job queue, a non-G-code upload,
225 // or a server that ignores `print`) we fall back to the explicit start below.
226 wxString test_msg;
227 if (!test(test_msg)) {
228 error_fn(std::move(test_msg));
229 return false;
230 }
231
232 const char *name = get_name();
233 const auto upload_filename = upload_data.upload_path.filename();
234 const auto upload_parent_path = upload_data.upload_path.parent_path();
235 //ORCA: upload_data.storage is plumbed from the (future) per-printer storage dropdown. When unset,
236 // fall back to the Moonraker-standard "gcodes" root. Reading it through here means a UI
237 // addition later (storage picker) needs no change to this method.
238 const std::string root = upload_data.storage.empty() ? std::string("gcodes") : upload_data.storage;
239
240 const bool want_start = upload_data.post_action == PrintHostPostUploadAction::StartPrint;
241
242 std::string url = make_url("server/files/upload");
243 bool result = true;
244 std::string uploaded_path;
245 bool moonraker_started_print = false;
246
247 //ORCA: gcode inside a .gcode.3mf is index-coded (Metadata/plate_<N>.gcode), so the upload names the
248 // plate via a 1-based `plateindex` (set only in the .3mf path, see Plater::send_gcode_legacy);
249 // servers that don't use it ignore the unknown form field.
250 const std::string plateindex = upload_data.extended("plateindex");
251
252 BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% to %3% (root=%4%, filename=%5%, plateindex=%6%, start_print=%7%)")
253 % name
254 % upload_data.source_path
255 % url
256 % root
257 % upload_filename.string()
258 % (plateindex.empty() ? "-" : plateindex)
259 % (want_start ? "true" : "false");
260
261 auto http = Http::post(std::move(url));
262 set_auth(http);
263 http.form_add("root", root);
264 if (!plateindex.empty())
265 http.form_add("plateindex", plateindex);
266 http.form_add("print", want_start ? "true" : "false");
267 http.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
268 .on_complete([&](std::string body, unsigned status) {
269 BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: upload HTTP %2%: %3%") % name % status % body;
270 try {
271 std::stringstream ss(body);
272 pt::ptree ptree;
273 pt::read_json(ss, ptree);
274
275 //ORCA: unlike the other endpoints (compare result.klippy_state in test()), the upload
276 // answers with a bare object, not a {"result": ...} envelope: Moonraker's
277 // FileUploadHandler writes finalize_upload()'s dict straight to the response, so
278 // item, print_started and print_queued are top-level. Reading them under result.
279 // silently took the fallbacks below on every upload.
280 //ORCA: Moonraker confirms the storage-relative path in item.path. We pass exactly
281 // that string to /printer/print/start so any server-side renaming (.ufp stored as
282 // .gcode, surrounding whitespace and leading slashes stripped) is respected.
283 const auto stored_path = ptree.get_optional<std::string>("item.path");
284 if (stored_path) {
285 uploaded_path = *stored_path;
286 } else {
287 //ORCA: fallback if the server response omits item.path (older Moonraker, or
288 // a buddy-fork that returns a slimmer envelope). Use the original filename.
289 uploaded_path = upload_filename.string();
290 BOOST_LOG_TRIVIAL(warning) << boost::format(
291 "%1%: upload response missing item.path, falling back to original filename `%2%`")
292 % name % uploaded_path;
293 }
294 moonraker_started_print = ptree.get<bool>("print_started", false) ||
295 ptree.get<bool>("print_queued", false);
296 } catch (const std::exception &ex) {
297 BOOST_LOG_TRIVIAL(warning) << boost::format(
298 "%1%: could not parse upload response (%2%); falling back to original filename")
299 % name % ex.what();
300 uploaded_path = upload_filename.string();
301 }
302 })
303 .on_error([&](std::string body, std::string error, unsigned status) {
304 BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading to %2%: %3%, HTTP %4%, body: `%5%`")
305 % name % url % error % status % body;
306 error_fn(format_error(body, error, status));
307 result = false;
308 })
309 .on_progress([&](Http::Progress progress, bool &cancel) {
310 progress_fn(std::move(progress), cancel);
311 if (cancel) {
312 BOOST_LOG_TRIVIAL(info) << name << ": Upload canceled";
313 result = false;
314 }
315 })
316#ifdef WIN32
317 .ssl_revoke_best_effort(m_ssl_revoke_best_effort)
318#endif
319 .perform_sync();
320
321 if (!result)
322 return false;
323
324 // Fallback only when Moonraker neither started nor queued the print. If the
325 // printer cannot start it, the error from this request is what the user sees.
326 if (want_start && !uploaded_path.empty() && !moonraker_started_print) {
327 wxString start_msg;
328 if (!start_print(start_msg, uploaded_path)) {
329 error_fn(std::move(start_msg));
330 return false;
331 }
332 }
333 return true;
334}
bool test(wxString &curl_msg) const override
Definition Moonraker.cpp:61
bool start_print(wxString &error_msg, const std::string &filename) const
Definition Moonraker.cpp:175

References Slic3r::PrintHostUpload::extended(), Slic3r::PrintHost::format_error(), get_name(), Slic3r::http, m_ssl_revoke_best_effort, make_url(), Slic3r::Http::post(), Slic3r::PrintHostUpload::post_action, set_auth(), Slic3r::PrintHostUpload::source_path, start_print(), Slic3r::StartPrint, Slic3r::PrintHostUpload::storage, test(), and Slic3r::PrintHostUpload::upload_path.

Here is the call graph for this function:

Member Data Documentation

◆ m_apikey

std::string Slic3r::Moonraker::m_apikey
protected

Referenced by Moonraker(), get_apikey(), and set_auth().

◆ m_cafile

std::string Slic3r::Moonraker::m_cafile
protected

Referenced by Moonraker(), get_cafile(), and set_auth().

◆ m_host

std::string Slic3r::Moonraker::m_host
protected

Referenced by Moonraker(), get_host(), and make_url().

◆ m_ssl_revoke_best_effort

bool Slic3r::Moonraker::m_ssl_revoke_best_effort
protected

The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/Utils/Moonraker.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/Utils/Moonraker.cpp