Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/xs
diff options
context:
space:
mode:
authorVojtech Kral <vojtech@kral.hk>2018-05-23 13:47:39 +0300
committerbubnikv <bubnikv@gmail.com>2018-06-21 11:44:29 +0300
commit1ba81655e2685c40b5c345684868e8d6d96cee2b (patch)
treec9a512216bc90caac9556f20d025093e2f71d46b /xs
parenta3a8333d203606d2c8f404e9e5e7957c6105d1db (diff)
Octoprint: Add a dialog for setting the filename/path
and a "print now" option cf. #880, #245, #55, #87
Diffstat (limited to 'xs')
-rw-r--r--xs/src/slic3r/GUI/MsgDialog.hpp2
-rw-r--r--xs/src/slic3r/Utils/Http.cpp39
-rw-r--r--xs/src/slic3r/Utils/Http.hpp35
-rw-r--r--xs/src/slic3r/Utils/OctoPrint.cpp81
-rw-r--r--xs/src/slic3r/Utils/OctoPrint.hpp2
-rw-r--r--xs/xsp/Utils_OctoPrint.xsp2
6 files changed, 140 insertions, 21 deletions
diff --git a/xs/src/slic3r/GUI/MsgDialog.hpp b/xs/src/slic3r/GUI/MsgDialog.hpp
index 2d570a0bf..ca349eb5c 100644
--- a/xs/src/slic3r/GUI/MsgDialog.hpp
+++ b/xs/src/slic3r/GUI/MsgDialog.hpp
@@ -28,6 +28,8 @@ struct MsgDialog : wxDialog
MsgDialog &operator=(const MsgDialog &) = delete;
virtual ~MsgDialog();
+ // TODO: refactor with CreateStdDialogButtonSizer usage
+
protected:
enum {
CONTENT_WIDTH = 500,
diff --git a/xs/src/slic3r/Utils/Http.cpp b/xs/src/slic3r/Utils/Http.cpp
index 0826284d8..adc8ac816 100644
--- a/xs/src/slic3r/Utils/Http.cpp
+++ b/xs/src/slic3r/Utils/Http.cpp
@@ -50,6 +50,9 @@ struct Http::priv
static size_t writecb(void *data, size_t size, size_t nmemb, void *userp);
static int xfercb(void *userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
static int xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow);
+
+ void form_add_file(const char *name, const char *path, const char* filename);
+
std::string curl_error(CURLcode curlcode);
std::string body_size_error();
void http_perform();
@@ -135,6 +138,26 @@ int Http::priv::xfercb_legacy(void *userp, double dltotal, double dlnow, double
return xfercb(userp, dltotal, dlnow, ultotal, ulnow);
}
+void Http::priv::form_add_file(const char *name, const char *path, const char* filename)
+{
+ if (filename != nullptr) {
+ ::curl_formadd(&form, &form_end,
+ CURLFORM_COPYNAME, name,
+ CURLFORM_FILE, path,
+ CURLFORM_FILENAME, filename,
+ CURLFORM_CONTENTTYPE, "application/octet-stream",
+ CURLFORM_END
+ );
+ } else {
+ ::curl_formadd(&form, &form_end,
+ CURLFORM_COPYNAME, name,
+ CURLFORM_FILE, path,
+ CURLFORM_CONTENTTYPE, "application/octet-stream",
+ CURLFORM_END
+ );
+ }
+}
+
std::string Http::priv::curl_error(CURLcode curlcode)
{
return (boost::format("%1% (%2%)")
@@ -265,17 +288,15 @@ Http& Http::form_add(const std::string &name, const std::string &contents)
return *this;
}
-Http& Http::form_add_file(const std::string &name, const std::string &filename)
+Http& Http::form_add_file(const std::string &name, const std::string &path)
{
- if (p) {
- ::curl_formadd(&p->form, &p->form_end,
- CURLFORM_COPYNAME, name.c_str(),
- CURLFORM_FILE, filename.c_str(),
- CURLFORM_CONTENTTYPE, "application/octet-stream",
- CURLFORM_END
- );
- }
+ if (p) { p->form_add_file(name.c_str(), path.c_str(), nullptr); }
+ return *this;
+}
+Http& Http::form_add_file(const std::string &name, const std::string &path, const std::string &filename)
+{
+ if (p) { p->form_add_file(name.c_str(), path.c_str(), filename.c_str()); }
return *this;
}
diff --git a/xs/src/slic3r/Utils/Http.hpp b/xs/src/slic3r/Utils/Http.hpp
index 7ed8196e6..2b8126334 100644
--- a/xs/src/slic3r/Utils/Http.hpp
+++ b/xs/src/slic3r/Utils/Http.hpp
@@ -16,11 +16,11 @@ private:
public:
struct Progress
{
- size_t dltotal;
- size_t dlnow;
- size_t ultotal;
- size_t ulnow;
-
+ size_t dltotal; // Total bytes to download
+ size_t dlnow; // Bytes downloaded so far
+ size_t ultotal; // Total bytes to upload
+ size_t ulnow; // Bytes uploaded so far
+
Progress(size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow) :
dltotal(dltotal), dlnow(dlnow), ultotal(ultotal), ulnow(ulnow)
{}
@@ -33,6 +33,8 @@ public:
Http(Http &&other);
+ // These are the primary constructors that create a HTTP object
+ // for a GET and a POST request respectively.
static Http get(std::string url);
static Http post(std::string url);
~Http();
@@ -41,21 +43,42 @@ public:
Http& operator=(const Http &) = delete;
Http& operator=(Http &&) = delete;
+ // Sets a maximum size of the data that can be received. The default is 5MB.
Http& size_limit(size_t sizeLimit);
+ // Sets a HTTP header field.
Http& header(std::string name, const std::string &value);
+ // Removes a header field.
Http& remove_header(std::string name);
+ // Sets a CA certificate file for usage with HTTPS. This is only supported on some backends,
+ // specifically, this is supported with OpenSSL and NOT supported with Windows and OS X native certificate store.
+ // See also ca_file_supported().
Http& ca_file(const std::string &filename);
+ // Add a HTTP multipart form field
Http& form_add(const std::string &name, const std::string &contents);
- Http& form_add_file(const std::string &name, const std::string &filename);
+ // Add a HTTP multipart form file data contents
+ Http& form_add_file(const std::string &name, const std::string &path);
+ // Same as above except also override the file's filename with a custom one
+ Http& form_add_file(const std::string &name, const std::string &path, const std::string &filename);
+ // Callback called on HTTP request complete
Http& on_complete(CompleteFn fn);
+ // Callback called on an error occuring at any stage of the requests: Url parsing, DNS lookup,
+ // TCP connection, HTTP transfer, and finally also when the response indicates an error (status >= 400).
+ // Therefore, a response body may or may not be present.
Http& on_error(ErrorFn fn);
+ // Callback called on data download/upload prorgess (called fairly frequently).
+ // See the `Progress` structure for description of the data passed.
+ // Writing a true-ish value into the cancel reference parameter cancels the request.
Http& on_progress(ProgressFn fn);
+ // Starts performing the request in a background thread
Ptr perform();
+ // Starts performing the request on the current thread
void perform_sync();
+ // Cancels a request in progress
void cancel();
+ // Tells whether current backend supports seting up a CA file using ca_file()
static bool ca_file_supported();
private:
Http(const std::string &url);
diff --git a/xs/src/slic3r/Utils/OctoPrint.cpp b/xs/src/slic3r/Utils/OctoPrint.cpp
index e63a16c38..1794c6024 100644
--- a/xs/src/slic3r/Utils/OctoPrint.cpp
+++ b/xs/src/slic3r/Utils/OctoPrint.cpp
@@ -1,20 +1,66 @@
#include "OctoPrint.hpp"
#include <algorithm>
+#include <boost/filesystem/path.hpp>
#include <boost/format.hpp>
+#include <boost/log/trivial.hpp>
#include <wx/frame.h>
#include <wx/event.h>
#include <wx/progdlg.h>
+#include <wx/sizer.h>
+#include <wx/stattext.h>
+#include <wx/textctrl.h>
+#include <wx/checkbox.h>
#include "libslic3r/PrintConfig.hpp"
#include "slic3r/GUI/GUI.hpp"
+#include "slic3r/GUI/MsgDialog.hpp"
#include "Http.hpp"
+namespace fs = boost::filesystem;
+
namespace Slic3r {
+struct SendDialog : public GUI::MsgDialog
+{
+ wxTextCtrl *txt_filename;
+ wxCheckBox *box_print;
+
+ SendDialog(const fs::path &path) :
+ MsgDialog(nullptr, _(L("Send G-Code to printer")), _(L("Upload to OctoPrint with the following filename:")), wxID_NONE),
+ txt_filename(new wxTextCtrl(this, wxID_ANY, path.filename().string())),
+ box_print(new wxCheckBox(this, wxID_ANY, _(L("Start printing after upload"))))
+ {
+ auto *label_dir_hint = new wxStaticText(this, wxID_ANY, _(L("Use forward slashes ( / ) as a directory separator if needed.")));
+ label_dir_hint->Wrap(CONTENT_WIDTH);
+
+ content_sizer->Add(txt_filename, 0, wxEXPAND);
+ content_sizer->Add(label_dir_hint);
+ content_sizer->AddSpacer(VERT_SPACING);
+ content_sizer->Add(box_print, 0, wxBOTTOM, 2*VERT_SPACING);
+
+ btn_sizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL));
+
+ txt_filename->SetFocus();
+ txt_filename->SetSelection(0, path.stem().size());
+
+ Fit();
+ }
+
+ fs::path filename() const {
+ // The buffer object that utf8_str() returns may just point to data owned by the source string
+ // so we need to copy the string in any case to be on the safe side.
+ return fs::path(txt_filename->GetValue().utf8_str().data());
+ }
+
+ bool print() const { return box_print->GetValue(); }
+};
+
+
+
OctoPrint::OctoPrint(DynamicPrintConfig *config) :
host(config->opt_string("octoprint_host")),
apikey(config->opt_string("octoprint_apikey")),
@@ -27,24 +73,39 @@ bool OctoPrint::test(wxString &msg) const
// it is ok to refer to `msg` from within the closure
bool res = true;
-
auto url = std::move(make_url("api/version"));
+
+ BOOST_LOG_TRIVIAL(info) << boost::format("Octoprint: Get version at: %1%") % url;
+
auto http = Http::get(std::move(url));
set_auth(http);
http.on_error([&](std::string, std::string error, unsigned status) {
+ BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error getting version: %1% (HTTP %2%)") % error % status;
res = false;
msg = format_error(error, status);
})
+ .on_complete([&](std::string body, unsigned) {
+ BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: Got version: %1%") % body;
+ })
.perform_sync();
return res;
}
-bool OctoPrint::send_gcode(const std::string &filename, bool print) const
+bool OctoPrint::send_gcode(const std::string &filename) const
{
enum { PROGRESS_RANGE = 1000 };
const auto errortitle = _(L("Error while uploading to the OctoPrint server"));
+ fs::path filepath(filename);
+
+ SendDialog send_dialog(filepath.filename().string());
+ if (send_dialog.ShowModal() != wxID_OK) { return false; }
+
+ const bool print = send_dialog.print();
+ const auto upload_filepath = send_dialog.filename();
+ const auto upload_filename = upload_filepath.filename();
+ const auto upload_parent_path = upload_filepath.parent_path();
wxProgressDialog progress_dialog(
_(L("OctoPrint upload")),
@@ -61,14 +122,26 @@ bool OctoPrint::send_gcode(const std::string &filename, bool print) const
bool res = true;
- auto http = Http::post(std::move(make_url("api/files/local")));
+ auto url = make_url("api/files/local");
+
+ BOOST_LOG_TRIVIAL(info) << boost::format("Octoprint: Uploading file %1% at %2%, filename: %3%, path: %4%, print: %5%")
+ % filepath
+ % url
+ % upload_filename
+ % upload_parent_path
+ % print;
+
+ auto http = Http::post(std::move(url));
set_auth(http);
http.form_add("print", print ? "true" : "false")
- .form_add_file("file", filename)
+ .form_add("path", upload_parent_path.string())
+ .form_add_file("file", filename, upload_filename.string())
.on_complete([&](std::string body, unsigned status) {
+ BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: File uploaded: HTTP %1%: %2%") % status % body;
progress_dialog.Update(PROGRESS_RANGE);
})
.on_error([&](std::string body, std::string error, unsigned status) {
+ BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error uploading file: %1% (HTTP %2%)") % error % status;
auto errormsg = wxString::Format("%s: %s", errortitle, format_error(error, status));
GUI::show_error(&progress_dialog, std::move(errormsg));
res = false;
diff --git a/xs/src/slic3r/Utils/OctoPrint.hpp b/xs/src/slic3r/Utils/OctoPrint.hpp
index 744b4fcc1..e278c8141 100644
--- a/xs/src/slic3r/Utils/OctoPrint.hpp
+++ b/xs/src/slic3r/Utils/OctoPrint.hpp
@@ -17,7 +17,7 @@ public:
OctoPrint(DynamicPrintConfig *config);
bool test(wxString &curl_msg) const;
- bool send_gcode(const std::string &filename, bool print = false) const;
+ bool send_gcode(const std::string &filename) const;
private:
std::string host;
std::string apikey;
diff --git a/xs/xsp/Utils_OctoPrint.xsp b/xs/xsp/Utils_OctoPrint.xsp
index 282a3055d..28610cb01 100644
--- a/xs/xsp/Utils_OctoPrint.xsp
+++ b/xs/xsp/Utils_OctoPrint.xsp
@@ -9,5 +9,5 @@
OctoPrint(DynamicPrintConfig *config);
~OctoPrint();
- bool send_gcode(std::string filename, bool print = false) const;
+ bool send_gcode(std::string filename) const;
};