Skip to content

Commit

Permalink
Octoprint (prusa3d#804)
Browse files Browse the repository at this point in the history
* Octoprint progress dialog

* Fix curl version on Windows
  • Loading branch information
vojtechkral authored and bubnikv committed Apr 4, 2018
1 parent 00324a1 commit b084006
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 40 deletions.
7 changes: 4 additions & 3 deletions doc/How to build - Windows.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Building Slic3r PE on Microsoft Windows

The currently supported way of building Slic3r PE on Windows is with MS Visual Studio 2013
The currently supported way of building Slic3r PE on Windows is with CMake and MS Visual Studio 2013
using our Perl binary distribution (compiled from official Perl sources).
You can use the free [Visual Studio 2013 Community Edition](https://www.visualstudio.com/vs/older-downloads/).
CMake installer can be downloaded from [the official website](https://cmake.org/download/).

Other setups (such as mingw + Strawberry Perl) _may_ work, but we cannot guarantee this will work
and cannot provide guidance.
Expand All @@ -26,8 +27,8 @@ Apart from wxWidgets and Perl, you will also need additional dependencies:

We have prepared a binary package of the listed libraries:

- 32 bit: [slic3r-destdir-32.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=slic3r-destdir-32.7z)
- 64 bit: [slic3r-destdir-64.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=slic3r-destdir-64.7z)
- 32 bit: [slic3r-destdir-32.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=2%2Fslic3r-destdir-32.7z)
- 64 bit: [slic3r-destdir-64.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=2%2Fslic3r-destdir-64.7z)

It is recommended you unpack this package into `C:\local\` as the environment
setup script expects it there.
Expand Down
2 changes: 1 addition & 1 deletion doc/deps-build/windows/slic3r-makedeps.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ if ($destdir -eq "") {
}

$BOOST = 'boost_1_63_0'
$CURL = 'curl-7.28.0'
$CURL = 'curl-7.58.0'
$TBB_SHA = 'a0dc9bf76d0120f917b641ed095360448cabc85b'
$TBB = "tbb-$TBB_SHA"

Expand Down
6 changes: 5 additions & 1 deletion lib/Slic3r/GUI/Plater.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1481,7 +1481,11 @@ sub on_export_completed {
# Send $self->{send_gcode_file} to OctoPrint.
if ($send_gcode) {
my $op = Slic3r::OctoPrint->new($self->{config});
$op->send_gcode($self->GetId(), $PROGRESS_BAR_EVENT, $ERROR_EVENT, $self->{send_gcode_file});
if ($op->send_gcode($self->{send_gcode_file})) {
$self->statusbar->SetStatusText(L("OctoPrint upload finished."));
} else {
$self->statusbar->SetStatusText("");
}
}

$self->{print_file} = undef;
Expand Down
73 changes: 64 additions & 9 deletions xs/src/slic3r/Utils/Http.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,20 @@ struct Http::priv
::curl_slist *headerlist;
std::string buffer;
size_t limit;
bool cancel;

std::thread io_thread;
Http::CompleteFn completefn;
Http::ErrorFn errorfn;
Http::ProgressFn progressfn;

priv(const std::string &url);
~priv();

static bool ca_file_supported(::CURL *curl);
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);
std::string curl_error(CURLcode curlcode);
std::string body_size_error();
void http_perform();
Expand All @@ -55,7 +59,8 @@ Http::priv::priv(const std::string &url) :
curl(::curl_easy_init()),
form(nullptr),
form_end(nullptr),
headerlist(nullptr)
headerlist(nullptr),
cancel(false)
{
if (curl == nullptr) {
throw std::runtime_error(std::string("Could not construct Curl object"));
Expand Down Expand Up @@ -112,6 +117,24 @@ size_t Http::priv::writecb(void *data, size_t size, size_t nmemb, void *userp)
return realsize;
}

int Http::priv::xfercb(void *userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
auto self = static_cast<priv*>(userp);
bool cb_cancel = false;

if (self->progressfn) {
Progress progress(dltotal, dlnow, ultotal, ulnow);
self->progressfn(progress, cb_cancel);
}

return self->cancel || cb_cancel;
}

int Http::priv::xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow)
{
return xfercb(userp, dltotal, dlnow, ultotal, ulnow);
}

std::string Http::priv::curl_error(CURLcode curlcode)
{
return (boost::format("%1% (%2%)")
Expand All @@ -132,6 +155,16 @@ void Http::priv::http_perform()
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
::curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(this));

::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
#if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 32
::curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xfercb);
::curl_easy_setopt(curl, CURLOPT_XFERINFODATA, static_cast<void*>(this));
(void)xfercb_legacy; // prevent unused function warning
#else
::curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, xfercb);
::curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, static_cast<void*>(this));
#endif

#ifndef NDEBUG
::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
#endif
Expand All @@ -149,16 +182,16 @@ void Http::priv::http_perform()
::curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status);

if (res != CURLE_OK) {
std::string error;
if (res == CURLE_WRITE_ERROR) {
error = std::move(body_size_error());
if (res == CURLE_ABORTED_BY_CALLBACK) {
Progress dummyprogress(0, 0, 0, 0);
bool cancel = true;
if (progressfn) { progressfn(dummyprogress, cancel); }
}
else if (res == CURLE_WRITE_ERROR) {
if (errorfn) { errorfn(std::move(buffer), std::move(body_size_error()), http_status); }
} else {
error = std::move(curl_error(res));
if (errorfn) { errorfn(std::move(buffer), std::move(curl_error(res)), http_status); }
};

if (errorfn) {
errorfn(std::move(buffer), std::move(error), http_status);
}
} else {
if (completefn) {
completefn(std::move(buffer), http_status);
Expand Down Expand Up @@ -258,6 +291,12 @@ Http& Http::on_error(ErrorFn fn)
return *this;
}

Http& Http::on_progress(ProgressFn fn)
{
if (p) { p->progressfn = std::move(fn); }
return *this;
}

Http::Ptr Http::perform()
{
auto self = std::make_shared<Http>(std::move(*this));
Expand All @@ -277,6 +316,11 @@ void Http::perform_sync()
if (p) { p->http_perform(); }
}

void Http::cancel()
{
if (p) { p->cancel = true; }
}

Http Http::get(std::string url)
{
return std::move(Http{std::move(url)});
Expand All @@ -297,5 +341,16 @@ bool Http::ca_file_supported()
return res;
}

std::ostream& operator<<(std::ostream &os, const Http::Progress &progress)
{
os << "Http::Progress("
<< "dltotal = " << progress.dltotal
<< ", dlnow = " << progress.dlnow
<< ", ultotal = " << progress.ultotal
<< ", ulnow = " << progress.ulnow
<< ")";
return os;
}


}
17 changes: 17 additions & 0 deletions xs/src/slic3r/Utils/Http.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,22 @@ class Http : public std::enable_shared_from_this<Http> {
private:
struct priv;
public:
struct Progress
{
size_t dltotal;
size_t dlnow;
size_t ultotal;
size_t ulnow;

Progress(size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow) :
dltotal(dltotal), dlnow(dlnow), ultotal(ultotal), ulnow(ulnow)
{}
};

typedef std::shared_ptr<Http> Ptr;
typedef std::function<void(std::string /* body */, unsigned /* http_status */)> CompleteFn;
typedef std::function<void(std::string /* body */, std::string /* error */, unsigned /* http_status */)> ErrorFn;
typedef std::function<void(Progress, bool& /* cancel */)> ProgressFn;

Http(Http &&other);

Expand All @@ -37,9 +50,11 @@ class Http : public std::enable_shared_from_this<Http> {

Http& on_complete(CompleteFn fn);
Http& on_error(ErrorFn fn);
Http& on_progress(ProgressFn fn);

Ptr perform();
void perform_sync();
void cancel();

static bool ca_file_supported();
private:
Expand All @@ -48,6 +63,8 @@ class Http : public std::enable_shared_from_this<Http> {
std::unique_ptr<priv> p;
};

std::ostream& operator<<(std::ostream &, const Http::Progress &);


}

Expand Down
66 changes: 42 additions & 24 deletions xs/src/slic3r/Utils/OctoPrint.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#include "OctoPrint.hpp"

#include <iostream>
#include <algorithm>
#include <boost/format.hpp>

#include <wx/frame.h>
#include <wx/event.h>
#include <wx/progdlg.h>

#include "libslic3r/PrintConfig.hpp"
#include "slic3r/GUI/GUI.hpp"
Expand Down Expand Up @@ -39,36 +40,53 @@ bool OctoPrint::test(wxString &msg) const
return res;
}

void OctoPrint::send_gcode(int windowId, int completeEvt, int errorEvt, const std::string &filename, bool print) const
bool OctoPrint::send_gcode(const std::string &filename, bool print) const
{
enum { PROGRESS_RANGE = 1000 };

const auto errortitle = _(L("Error while uploading to the OctoPrint server"));

wxProgressDialog progress_dialog(
_(L("OctoPrint upload")),
_(L("Sending G-code file to the OctoPrint server...")),
PROGRESS_RANGE, nullptr, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
progress_dialog.Pulse();

wxString test_msg;
if (!test(test_msg)) {
auto errormsg = wxString::Format("%s: %s", errortitle, test_msg);
GUI::show_error(&progress_dialog, std::move(errormsg));
return false;
}

bool res = true;

auto http = Http::post(std::move(make_url("api/files/local")));
set_auth(http);
http.form_add("print", print ? "true" : "false")
.form_add_file("file", filename)
.on_complete([=](std::string body, unsigned status) {
wxWindow *window = wxWindow::FindWindowById(windowId);
if (window == nullptr) { return; }

wxCommandEvent* evt = new wxCommandEvent(completeEvt);
evt->SetString(_(L("G-code file successfully uploaded to the OctoPrint server")));
evt->SetInt(100);
wxQueueEvent(window, evt);
.on_complete([&](std::string body, unsigned status) {
progress_dialog.Update(PROGRESS_RANGE);
})
.on_error([&](std::string body, std::string error, unsigned status) {
auto errormsg = wxString::Format("%s: %s", errortitle, format_error(error, status));
GUI::show_error(&progress_dialog, std::move(errormsg));
res = false;
})
.on_error([=](std::string body, std::string error, unsigned status) {
wxWindow *window = wxWindow::FindWindowById(windowId);
if (window == nullptr) { return; }

wxCommandEvent* evt_complete = new wxCommandEvent(completeEvt);
evt_complete->SetInt(100);
wxQueueEvent(window, evt_complete);

wxCommandEvent* evt_error = new wxCommandEvent(errorEvt);
evt_error->SetString(wxString::Format("%s: %s",
_(L("Error while uploading to the OctoPrint server")),
format_error(error, status)));
wxQueueEvent(window, evt_error);
.on_progress([&](Http::Progress progress, bool &cancel) {
if (cancel) {
// Upload was canceled
res = false;
} else if (progress.ultotal > 0) {
int value = PROGRESS_RANGE * progress.ulnow / progress.ultotal;
cancel = !progress_dialog.Update(std::min(value, PROGRESS_RANGE - 1)); // Cap the value to prevent premature dialog closing
} else {
cancel = !progress_dialog.Pulse();
}
})
.perform();
.perform_sync();

return res;
}

void OctoPrint::set_auth(Http &http) const
Expand Down
2 changes: 1 addition & 1 deletion xs/src/slic3r/Utils/OctoPrint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class OctoPrint
OctoPrint(DynamicPrintConfig *config);

bool test(wxString &curl_msg) const;
void send_gcode(int windowId, int completeEvt, int errorEvt, const std::string &filename, bool print = false) const;
bool send_gcode(const std::string &filename, bool print = false) const;
private:
std::string host;
std::string apikey;
Expand Down
2 changes: 1 addition & 1 deletion xs/xsp/Utils_OctoPrint.xsp
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
OctoPrint(DynamicPrintConfig *config);
~OctoPrint();

void send_gcode(int windowId, int completeEvt, int errorEvt, std::string filename, bool print = false) const;
bool send_gcode(std::string filename, bool print = false) const;
};

0 comments on commit b084006

Please sign in to comment.