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

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

Inheritance diagram for Slic3r::SimplyPrint:
Collaboration diagram for Slic3r::SimplyPrint:

Public Types

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

Public Member Functions

 SimplyPrint (DynamicPrintConfig *config)
 ~SimplyPrint () override=default
const char * get_name () const override
bool can_test () const override
bool has_auto_discovery () const override
bool is_cloud () const override
std::string get_host () const override
GUI::OAuthParams get_oauth_params () const
void save_oauth_credential (const GUI::OAuthResult &cred) const
wxString get_test_ok_msg () const override
wxString get_test_failed_msg (wxString &msg) const override
bool test (wxString &curl_msg) const override
PrintHostPostUploadActions get_post_upload_actions () const override
bool upload (PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const override
bool is_logged_in () const override
void log_out () const override
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 get_storage (wxArrayString &, wxArrayString &) 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

virtual wxString format_error (const std::string &body, const std::string &error, unsigned status) const

Static Protected Member Functions

static wxString timed_out_message ()

Private Member Functions

void load_oauth_credential ()
bool do_api_call (std::function< Http(bool)> build_request, std::function< bool(std::string, unsigned)> on_complete, std::function< bool(std::string, std::string, unsigned)> on_error) const
 Call the given SimplyPrint API, and if the token expired do a token refresh then retry.
bool do_temp_upload (const boost::filesystem::path &file_path, const std::string &chunk_id, const std::string &filename, ProgressFn prorgess_fn, ErrorFn error_fn) const
 Upload a temp file and open SimplyPrint panel for file importing.
bool do_chunk_upload (const boost::filesystem::path &file_path, const std::string &filename, ProgressFn prorgess_fn, ErrorFn error_fn) const

Private Attributes

std::string cred_file
std::map< std::string, std::string > cred

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

◆ SimplyPrint()

Slic3r::SimplyPrint::SimplyPrint ( DynamicPrintConfig * config)
130{
131 cred_file = (boost::filesystem::path(data_dir()) / OAUTH_CREDENTIAL_PATH).make_preferred().string();
133}
void load_oauth_credential()
Definition SimplyPrint.cpp:168
std::string cred_file
Definition SimplyPrint.hpp:18
static const std::string OAUTH_CREDENTIAL_PATH
Definition SimplyPrint.cpp:60
const std::string & data_dir()
Definition utils.cpp:365

References SimplyPrint(), cred_file, Slic3r::data_dir(), load_oauth_credential(), and Slic3r::OAUTH_CREDENTIAL_PATH.

Referenced by SimplyPrint().

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

◆ ~SimplyPrint()

Slic3r::SimplyPrint::~SimplyPrint ( )
overridedefault

Member Function Documentation

◆ can_test()

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

Implements Slic3r::PrintHost.

59{ return true; }

◆ do_api_call()

bool Slic3r::SimplyPrint::do_api_call ( std::function< Http(bool)> build_request,
std::function< bool(std::string, unsigned)> on_complete,
std::function< bool(std::string, std::string, unsigned)> on_error ) const
private

Call the given SimplyPrint API, and if the token expired do a token refresh then retry.

Parameters
build_requestthe http request builder
on_complete
on_error
Returns
whether the API call succeeded
214{
215 if (cred.find("access_token") == cred.end()) {
216 return false;
217 }
218
219 bool res = true;
220
221 const auto create_request = [&build_request, &res, &on_complete](const std::string& access_token, bool is_retry) {
222 auto http = build_request(is_retry);
223 set_auth(http, access_token);
224 http.header("User-Agent", "SimplyPrint Orca Plugin")
225 .on_complete([&](std::string body, unsigned http_status) {
226 res = on_complete(body, http_status);
227 });
228
229 return http;
230 };
231
232 create_request(cred.at("access_token"), false)
233 .on_error([&res, &on_error, this, &create_request](std::string body, std::string error, unsigned http_status) {
234 if (http_status == 401) {
235 // Refresh token
236 BOOST_LOG_TRIVIAL(warning) << boost::format("SimplyPrint: Access token invalid: %1%, HTTP %2%, body: `%3%`") % error %
237 http_status % body;
238 BOOST_LOG_TRIVIAL(info) << "SimplyPrint: Attempt to refresh access token";
239
240 auto http = Http::post(TOKEN_URL);
241 http.timeout_connect(5)
242 .timeout_max(5)
243 .form_add("grant_type", "refresh_token")
244 .form_add("client_id", CLIENT_ID)
245 .form_add("refresh_token", cred.at("refresh_token"))
246 .on_complete([this, &res, &on_error, &create_request](std::string body, unsigned http_status) {
247 GUI::OAuthResult r;
249 if (r.success) {
250 BOOST_LOG_TRIVIAL(info) << "SimplyPrint: Successfully refreshed access token";
251 this->save_oauth_credential(r);
252
253 // Run the api call again
254 create_request(r.access_token, true)
255 .on_error([&res, &on_error](std::string body, std::string error, unsigned http_status) {
256 res = on_error(body, error, http_status);
257 })
258 .perform_sync();
259 } else {
260 BOOST_LOG_TRIVIAL(error)
261 << boost::format("SimplyPrint: Failed to refresh access token: %1%, body: `%2%`") % r.error_message % body;
262 res = on_error(body, r.error_message, http_status);
263 }
264 })
265 .on_error([&res, &on_error](std::string body, std::string error, unsigned http_status) {
266 BOOST_LOG_TRIVIAL(error)
267 << boost::format("SimplyPrint: Failed to refresh access token: %1%, HTTP %2%, body: `%3%`") % error %
268 http_status % body;
269 res = on_error(body, error, http_status);
270 })
271 .perform_sync();
272 } else {
273 res = on_error(body, error, http_status);
274 }
275 })
276 .perform_sync();
277
278 return res;
279}
static void parse_token_response(const std::string &body, bool error, OAuthResult &result)
Definition OAuthJob.cpp:25
static Http post(std::string url)
Definition Http.cpp:891
void save_oauth_credential(const GUI::OAuthResult &cred) const
Definition SimplyPrint.cpp:187
std::map< std::string, std::string > cred
Definition SimplyPrint.hpp:19
static const std::string CLIENT_ID
Definition SimplyPrint.cpp:58
static void set_auth(Http &http, const std::string &access_token)
Definition SimplyPrint.cpp:114
static const std::string TOKEN_URL
Definition SimplyPrint.cpp:61
@ http
Definition IPrinterAgent.hpp:64

References Slic3r::GUI::OAuthResult::access_token, Slic3r::CLIENT_ID, cred, do_api_call(), Slic3r::GUI::OAuthResult::error_message, Slic3r::http, Slic3r::GUI::OAuthJob::parse_token_response(), Slic3r::Http::post(), save_oauth_credential(), Slic3r::set_auth(), Slic3r::GUI::OAuthResult::success, and Slic3r::TOKEN_URL.

Referenced by do_api_call(), do_chunk_upload(), do_temp_upload(), and test().

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

◆ do_chunk_upload()

bool Slic3r::SimplyPrint::do_chunk_upload ( const boost::filesystem::path & file_path,
const std::string & filename,
ProgressFn prorgess_fn,
ErrorFn error_fn ) const
private
372{
373 const auto file_size = boost::filesystem::file_size(file_path);
374#ifdef SIMPLYPRINT_TEST
375 constexpr auto buffer_size = MAX_SINGLE_UPLOAD_FILE_SIZE;
376#else
377 constexpr auto buffer_size = MAX_SINGLE_UPLOAD_FILE_SIZE - 1000000;
378#endif
379
380 const auto chunk_amount = (size_t)ceil((double) file_size / buffer_size);
381
382 std::string chunk_id;
383 std::string delete_token;
384
385 // Tell SimplyPrint that the upload has failed and the chunks should be deleted
386 // Note: any error happens here won't be notified to the user
387 const auto clean_up = [this, &chunk_id, &delete_token]() {
388 if (chunk_id.empty()) {
389 // The initial upload failed, do nothing
390 BOOST_LOG_TRIVIAL(warning) << "SimplyPrint: Initial chunk upload failed, skip delete";
391 return;
392 }
393
394 assert(!delete_token.empty());
395
396 BOOST_LOG_TRIVIAL(info) << boost::format("SimplyPrint: Deleting file chunk %s...") % chunk_id;
397 const std::vector<std::pair<std::string, std::string>> query_parameters{
398 {"id", chunk_id},
399 {"temp", "true"},
400 {"delete", delete_token},
401 };
402 const auto url = (boost::format("%s?%s") % CHUNCK_RECEIVE_URL % url_encode(query_parameters)).str();
404 [&url](bool is_retry) {
405 auto http = Http::get(url);
406 return http;
407 },
408 [&chunk_id](std::string body, unsigned status) {
409 BOOST_LOG_TRIVIAL(info) << boost::format("SimplyPrint: File chunk %1% deleted: HTTP %2%: %3%") % chunk_id % status % body;
410 return true;
411 },
412 [&chunk_id](std::string body, std::string error, unsigned status) {
413 BOOST_LOG_TRIVIAL(warning) << boost::format("SimplyPrint: Error deleting file chunk %1%: %2%, HTTP %3%, body: `%4%`") %
414 chunk_id % error % status % body;
415 return false;
416 });
417 };
418
419 // Do chunk upload
420 for (size_t i = 0; i < chunk_amount; i++) {
421 std::string url;
422 {
423 std::vector<std::pair<std::string, std::string>> query_parameters{
424 {"i", std::to_string(i)},
425 {"temp", "true"},
426 };
427 if (i == 0) {
428 query_parameters.emplace_back("filename", filename);
429 query_parameters.emplace_back("chunks", std::to_string(chunk_amount));
430 query_parameters.emplace_back("totalsize", std::to_string(file_size));
431 } else {
432 query_parameters.emplace_back("id", chunk_id);
433 }
434 url = (boost::format("%s?%s") % CHUNCK_RECEIVE_URL % url_encode(query_parameters)).str();
435 }
436
437 // Calculate the offset and length of current chunk
438 const boost::filesystem::ifstream::off_type offset = i * buffer_size;
439 const size_t length = i == (chunk_amount - 1) ? file_size - offset : buffer_size;
440
441 const bool succ = do_api_call(
442 [&url, &file_path, &filename, i, chunk_amount, file_size, offset, length, prorgess_fn](bool is_retry) {
443 BOOST_LOG_TRIVIAL(info) << boost::format("SimplyPrint: Start uploading file chunk [%1%/%2%]...") % (i + 1) % chunk_amount;
444 auto http = Http::post(url);
445 http.form_add_file("file", file_path, filename, offset, length);
446
447 http.on_progress([&prorgess_fn, file_size, offset](Http::Progress progress, bool& cancel) {
448 progress.ultotal = file_size;
449 progress.ulnow += offset;
450
451 prorgess_fn(std::move(progress), cancel);
452 });
453
454 return http;
455 },
456 [&error_fn, i, chunk_amount, &chunk_id, &delete_token](std::string body, unsigned status) {
457 BOOST_LOG_TRIVIAL(info) << boost::format("SimplyPrint: File chunk [%1%/%2%] uploaded: HTTP %3%: %4%") % (i + 1) % chunk_amount % status % body;
458 if (i == 0) {
459 // First chunk, parse chunk id
460 const auto j = nlohmann::json::parse(body, nullptr, false, true);
461 if (j.is_discarded()) {
462 BOOST_LOG_TRIVIAL(error) << "SimplyPrint: Invalid or no JSON data on ChunkReceive: " << body;
463 error_fn(_L("Unknown error"));
464 return false;
465 }
466
467 if (j.find("id") == j.end() || j.find("delete_token") == j.end()) {
468 BOOST_LOG_TRIVIAL(error) << "SimplyPrint: Invalid or no JSON data on ChunkReceive: " << body;
469 error_fn(_L("Unknown error"));
470 return false;
471 }
472
473 const unsigned long id = j["id"];
474
475 chunk_id = std::to_string(id);
476 delete_token = j["delete_token"];
477 }
478 return true;
479 },
480 [this, &error_fn, i, chunk_amount](std::string body, std::string error, unsigned status) {
481 BOOST_LOG_TRIVIAL(error) << boost::format("SimplyPrint: Error uploading file chunk [%1%/%2%]: %3%, HTTP %4%, body: `%5%`") %
482 (i + 1) % chunk_amount % error % status % body;
483 error_fn(format_error(body, error, status));
484 return false;
485 });
486
487 if (!succ) {
488 clean_up();
489 return false;
490 }
491 }
492
493 assert(!chunk_id.empty());
494
495 // Finally, complete the upload using the chunk id
496 const bool succ = do_temp_upload({}, chunk_id, filename, prorgess_fn, error_fn);
497 if (!succ) {
498 clean_up();
499 }
500
501 return succ;
502}
#define _L(s)
Definition OBJ.cpp:34
static Http get(std::string url)
Definition Http.cpp:886
virtual wxString format_error(const std::string &body, const std::string &error, unsigned status) const
Definition PrintHost.cpp:202
bool do_temp_upload(const boost::filesystem::path &file_path, const std::string &chunk_id, const std::string &filename, ProgressFn prorgess_fn, ErrorFn error_fn) const
Upload a temp file and open SimplyPrint panel for file importing.
Definition SimplyPrint.cpp:305
bool do_api_call(std::function< Http(bool)> build_request, std::function< bool(std::string, unsigned)> on_complete, std::function< bool(std::string, std::string, unsigned)> on_error) const
Call the given SimplyPrint API, and if the token expired do a token refresh then retry.
Definition SimplyPrint.cpp:211
double length(const Points &pts)
Definition MultiPoint.hpp:181
static std::string url_encode(const std::vector< std::pair< std::string, std::string > > query)
Definition SimplyPrint.cpp:99
static constexpr uint64_t MAX_SINGLE_UPLOAD_FILE_SIZE
Definition SimplyPrint.cpp:65
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582
static const std::string CHUNCK_RECEIVE_URL
Definition SimplyPrint.cpp:67

References _L, Slic3r::CHUNCK_RECEIVE_URL, do_api_call(), do_chunk_upload(), do_temp_upload(), Slic3r::PrintHost::format_error(), Slic3r::Http::get(), Slic3r::http, Slic3r::length(), Slic3r::MAX_SINGLE_UPLOAD_FILE_SIZE, Slic3r::offset(), Slic3r::Http::post(), Slic3r::Http::Progress::ulnow, Slic3r::Http::Progress::ultotal, and Slic3r::url_encode().

Referenced by do_chunk_upload(), and upload().

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

◆ do_temp_upload()

bool Slic3r::SimplyPrint::do_temp_upload ( const boost::filesystem::path & file_path,
const std::string & chunk_id,
const std::string & filename,
ProgressFn prorgess_fn,
ErrorFn error_fn ) const
private

Upload a temp file and open SimplyPrint panel for file importing.

Parameters
file_pathfor file smaller than 100MB, this is the file path, otherwise must left empty
chunk_idfor file greater than 100MB, this is the chunk id returned by the ChunkReceive API, otherwise must left empty
filenamethe target file name
prorgess_fn
error_fn
Returns
whether upload succeeded
310{
311 if (file_path.empty() == chunk_id.empty()) {
312 BOOST_LOG_TRIVIAL(error) << "SimplyPrint: Invalid arguments: both file_path and chunk_id are set or not provided";
313 error_fn(_L("Internal error"));
314 return false;
315 }
316
317 return do_api_call(
318 [&file_path, &chunk_id, &prorgess_fn, &filename](bool is_retry) {
319 auto http = Http::post(URL_BASE_HOME"/api/files/TempUpload");
320 if (!file_path.empty()) {
321 http.form_add_file("file", file_path, filename);
322 } else {
323 http.form_add("chunkId", chunk_id);
324 }
325 http.on_progress([&prorgess_fn](Http::Progress progress, bool& cancel) { prorgess_fn(std::move(progress), cancel); });
326
327 return http;
328 },
329 [&error_fn, &filename](std::string body, unsigned status) {
330 BOOST_LOG_TRIVIAL(info) << boost::format("SimplyPrint: File uploaded: HTTP %1%: %2%") % status % body;
331
332 // Get file UUID
333 const auto j = nlohmann::json::parse(body, nullptr, false, true);
334 if (j.is_discarded()) {
335 BOOST_LOG_TRIVIAL(error) << "SimplyPrint: Invalid or no JSON data on token response: " << body;
336 error_fn(_L("Unknown error"));
337 return false;
338 }
339
340 if (j.find("uuid") == j.end()) {
341 BOOST_LOG_TRIVIAL(error) << "SimplyPrint: Invalid or no JSON data on token response: " << body;
342 error_fn(_L("Unknown error"));
343 return false;
344 }
345 const std::string uuid = j["uuid"];
346
347 // Launch external browser for file importing after uploading
348 const auto url = URL_BASE_HOME"/panel?" + url_encode({{"import", "tmp:" + uuid}, {"filename", filename}});
349
351 wxLaunchDefaultBrowser(url);
352 } else {
353 // The tab switch queues a reload of the printer's home page, so switch synchronously
354 // first and queue the import page after it.
355 GUI::wxGetApp().CallAfter([url = wxString::FromUTF8(url)] {
356 const auto mainframe = GUI::wxGetApp().mainframe;
357 mainframe->select_tab(TAB_ID_MONITOR);
358 mainframe->load_printer_url(url);
359 });
360 }
361
362 return true;
363 },
364 [this, &error_fn](std::string body, std::string error, unsigned status) {
365 BOOST_LOG_TRIVIAL(error) << boost::format("SimplyPrint: Error uploading file : %1%, HTTP %2%, body: `%3%`") % error % status % body;
366 error_fn(format_error(body, error, status));
367 return false;
368 });
369}
#define TAB_ID_MONITOR
Definition MainFrame.hpp:62
#define URL_BASE_HOME
Definition SimplyPrint.cpp:51
static bool should_open_in_external_browser()
Definition SimplyPrint.cpp:116

References _L, do_api_call(), do_temp_upload(), Slic3r::PrintHost::format_error(), Slic3r::http, Slic3r::Http::post(), Slic3r::should_open_in_external_browser(), TAB_ID_MONITOR, URL_BASE_HOME, and Slic3r::url_encode().

Referenced by do_chunk_upload(), do_temp_upload(), and upload().

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

◆ 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}
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_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::SimplyPrint::get_host ( ) const
inlineoverridevirtual

Implements Slic3r::PrintHost.

62{ return "https://simplyprint.io"; }

◆ 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::SimplyPrint::get_name ( ) const
inlineoverridevirtual

Implements Slic3r::PrintHost.

58{ return "SimplyPrint"; }

◆ get_oauth_params()

GUI::OAuthParams Slic3r::SimplyPrint::get_oauth_params ( ) const
136{
137 const auto verification_code = generate_verification_code();
138 // SimplyPrint uses S256 for PKCE
139 const auto code_challenge = sha256b64(verification_code);
140 const auto state = generate_verification_code();
141
142 const std::vector<std::pair<std::string, std::string>> query_parameters{
143 {"client_id", CLIENT_ID},
144 {"redirect_uri", CALLBACK_URL},
145 {"scope", CLIENT_SCOPES},
146 {"response_type", RESPONSE_TYPE},
147 {"state", state},
148 {"code_challenge", code_challenge},
149 {"code_challenge_method", "S256"},
150 };
151 const auto login_url = (boost::format(URL_BASE_HOME"/panel/oauth2/authorize?%s") % url_encode(query_parameters)).str();
152
153 return GUI::OAuthParams{
154 login_url,
155 CLIENT_ID,
160 URL_BASE_HOME"/login-success",
161 URL_BASE_HOME"/login-success",
162 TOKEN_URL,
163 verification_code,
164 state,
165 };
166}
static const std::string CLIENT_SCOPES
Definition SimplyPrint.cpp:59
static const std::string CALLBACK_URL
Definition SimplyPrint.cpp:56
static std::string generate_verification_code(int code_length=32)
Definition SimplyPrint.cpp:69
static constexpr boost::asio::ip::port_type CALLBACK_PORT
Definition SimplyPrint.cpp:55
static std::string sha256b64(const std::string &inputStr)
Definition SimplyPrint.cpp:79
static const std::string RESPONSE_TYPE
Definition SimplyPrint.cpp:57

References Slic3r::CALLBACK_PORT, Slic3r::CALLBACK_URL, Slic3r::CLIENT_ID, Slic3r::CLIENT_SCOPES, Slic3r::generate_verification_code(), get_oauth_params(), Slic3r::RESPONSE_TYPE, Slic3r::sha256b64(), Slic3r::TOKEN_URL, URL_BASE_HOME, and Slic3r::url_encode().

Referenced by get_oauth_params().

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

◆ get_post_upload_actions()

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

Implements Slic3r::PrintHost.

@ QueuePrint
Definition PrintHost.hpp:27

References Slic3r::QueuePrint.

◆ 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()

virtual bool Slic3r::PrintHost::get_storage ( wxArrayString & ,
wxArrayString &  ) const
inlinevirtualinherited

Reimplemented in Slic3r::Moonraker, Slic3r::PrusaConnect, and Slic3r::PrusaLink.

88{ return false; }

◆ get_test_failed_msg()

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

Implements Slic3r::PrintHost.

202{
203 return GUI::format_wxstr("%s: %s", _L("Could not connect to SimplyPrint"), msg.Truncate(256));
204}
wxString format_wxstr(const char *fmt, TArgs &&... args)
Definition format.hpp:22

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

Referenced by get_test_failed_msg().

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

◆ get_test_ok_msg()

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

Implements Slic3r::PrintHost.

199{ return _(L("Connected to SimplyPrint successfully!")); }
#define _(s)
Definition 3mf.cpp:306
#define L(s)
Definition ExtrusionEntity.cpp:25

References _, get_test_ok_msg(), and L.

Referenced by get_test_ok_msg().

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

◆ has_auto_discovery()

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

Implements Slic3r::PrintHost.

60{ return false; }

◆ is_cloud()

bool Slic3r::SimplyPrint::is_cloud ( ) const
inlineoverridevirtual

Reimplemented from Slic3r::PrintHost.

61{ return true; }

◆ is_logged_in()

bool Slic3r::SimplyPrint::is_logged_in ( ) const
inlineoverridevirtual

Reimplemented from Slic3r::PrintHost.

72{ return !cred.empty(); }

References cred.

◆ load_oauth_credential()

void Slic3r::SimplyPrint::load_oauth_credential ( )
private
169{
170 cred.clear();
171 if (boost::filesystem::exists(cred_file)) {
172 nlohmann::json j;
173 try {
174 boost::nowide::ifstream ifs(cred_file);
175 ifs >> j;
176 ifs.close();
177
178 cred["access_token"] = j["access_token"];
179 cred["refresh_token"] = j["refresh_token"];
180 } catch (std::exception& err) {
181 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": parse " << cred_file << " failed, reason = " << err.what();
182 cred.clear();
183 }
184 }
185}

References cred, cred_file, and load_oauth_credential().

Referenced by SimplyPrint(), and load_oauth_credential().

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

◆ log_out()

void Slic3r::SimplyPrint::log_out ( ) const
overridevirtual

Reimplemented from Slic3r::PrintHost.

207{
208 boost::nowide::remove(cred_file.c_str());
209}

References cred_file, and log_out().

Referenced by log_out().

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

◆ save_oauth_credential()

void Slic3r::SimplyPrint::save_oauth_credential ( const GUI::OAuthResult & cred) const
188{
189 nlohmann::json j;
190 j["access_token"] = cred.access_token;
191 j["refresh_token"] = cred.refresh_token;
192
193 boost::nowide::ofstream c;
194 c.open(cred_file, std::ios::out | std::ios::trunc);
195 c << j.dump(1, '\t') << std::endl;
196 c.close();
197}

References cred, cred_file, and save_oauth_credential().

Referenced by do_api_call(), and save_oauth_credential().

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::SimplyPrint::test ( wxString & curl_msg) const
overridevirtual

Implements Slic3r::PrintHost.

283{
284 if (cred.find("access_token") == cred.end()) {
285 return false;
286 }
287
288 return do_api_call(
289 [](bool is_retry) {
290 auto http = Http::get(URL_BASE_API"/oauth2/TokenInfo");
291 http.header("Accept", "application/json");
292 return http;
293 },
294 [](std::string body, unsigned) {
295 BOOST_LOG_TRIVIAL(info) << boost::format("SimplyPrint: Got token info: %1%") % body;
296 return true;
297 },
298 [](std::string body, std::string error, unsigned status) {
299 BOOST_LOG_TRIVIAL(error) << boost::format("SimplyPrint: Error getting token info: %1%, HTTP %2%, body: `%3%`") % error %
300 status % body;
301 return false;
302 });
303}
#define URL_BASE_API
Definition SimplyPrint.cpp:52

References cred, do_api_call(), Slic3r::Http::get(), Slic3r::http, test(), and URL_BASE_API.

Referenced by test().

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::SimplyPrint::upload ( PrintHostUpload upload_data,
ProgressFn prorgess_fn,
ErrorFn error_fn,
InfoFn info_fn ) const
overridevirtual

Implements Slic3r::PrintHost.

506{
507 if (cred.find("access_token") == cred.end()) {
508 error_fn(_L("SimplyPrint account not linked. Go to Connect options to set it up."));
509 return false;
510 }
511 const auto filename = upload_data.upload_path.filename().string();
512
513 if (boost::filesystem::file_size(upload_data.source_path) > MAX_SINGLE_UPLOAD_FILE_SIZE) {
514 // If file is over 100 MB, do chunk upload
515 return do_chunk_upload(upload_data.source_path, filename, prorgess_fn, error_fn);
516 } else {
517 // Normal upload
518 return do_temp_upload(upload_data.source_path, {}, filename, prorgess_fn, error_fn);
519 }
520}
bool do_chunk_upload(const boost::filesystem::path &file_path, const std::string &filename, ProgressFn prorgess_fn, ErrorFn error_fn) const
Definition SimplyPrint.cpp:371

References _L, cred, do_chunk_upload(), do_temp_upload(), Slic3r::MAX_SINGLE_UPLOAD_FILE_SIZE, Slic3r::PrintHostUpload::source_path, upload(), and Slic3r::PrintHostUpload::upload_path.

Referenced by upload().

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

Member Data Documentation

◆ cred

std::map<std::string, std::string> Slic3r::SimplyPrint::cred
private

◆ cred_file

std::string Slic3r::SimplyPrint::cred_file
private

The documentation for this class was generated from the following files: