Merge branch 'master' of https://github.com/prusa3d/Slic3r into time_estimate
This commit is contained in:
commit
4ee365194a
@ -53,7 +53,7 @@ sub new {
|
|||||||
bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height
|
bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height
|
||||||
serial_port serial_speed octoprint_host octoprint_apikey octoprint_cafile
|
serial_port serial_speed octoprint_host octoprint_apikey octoprint_cafile
|
||||||
nozzle_diameter single_extruder_multi_material wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width
|
nozzle_diameter single_extruder_multi_material wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width
|
||||||
wipe_tower_rotation_angle extruder_colour filament_colour max_print_height
|
wipe_tower_rotation_angle extruder_colour filament_colour max_print_height printer_model
|
||||||
)]);
|
)]);
|
||||||
# C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm
|
# C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm
|
||||||
$self->{model} = Slic3r::Model->new;
|
$self->{model} = Slic3r::Model->new;
|
||||||
@ -1888,6 +1888,9 @@ sub on_config_change {
|
|||||||
$self->{preview3D}->set_number_extruders(scalar(@{$extruder_colors}));
|
$self->{preview3D}->set_number_extruders(scalar(@{$extruder_colors}));
|
||||||
} elsif ($opt_key eq 'max_print_height') {
|
} elsif ($opt_key eq 'max_print_height') {
|
||||||
$update_scheduled = 1;
|
$update_scheduled = 1;
|
||||||
|
} elsif ($opt_key eq 'printer_model') {
|
||||||
|
# update to force bed selection (for texturing)
|
||||||
|
$update_scheduled = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,16 +405,27 @@ GLCanvas3D::Bed::EType GLCanvas3D::Bed::_detect_type() const
|
|||||||
const PresetBundle* bundle = get_preset_bundle();
|
const PresetBundle* bundle = get_preset_bundle();
|
||||||
if (bundle != nullptr)
|
if (bundle != nullptr)
|
||||||
{
|
{
|
||||||
const Preset& curr = bundle->printers.get_selected_preset();
|
const Preset* curr = &bundle->printers.get_selected_preset();
|
||||||
if (curr.config.has("bed_shape") && _are_equal(m_shape, dynamic_cast<const ConfigOptionPoints*>(curr.config.option("bed_shape"))->values))
|
while (curr != nullptr)
|
||||||
{
|
{
|
||||||
if ((curr.vendor != nullptr) && (curr.vendor->name == "Prusa Research"))
|
if (curr->config.has("bed_shape") && _are_equal(m_shape, dynamic_cast<const ConfigOptionPoints*>(curr->config.option("bed_shape"))->values))
|
||||||
{
|
{
|
||||||
if (boost::contains(curr.name, "MK2"))
|
if ((curr->vendor != nullptr) && (curr->vendor->name == "Prusa Research"))
|
||||||
type = MK2;
|
{
|
||||||
else if (boost::contains(curr.name, "MK3"))
|
if (boost::contains(curr->name, "MK2"))
|
||||||
type = MK3;
|
{
|
||||||
|
type = MK2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (boost::contains(curr->name, "MK3"))
|
||||||
|
{
|
||||||
|
type = MK3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curr = bundle->printers.get_preset_parent(*curr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include <wx/image.h>
|
#include <wx/image.h>
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -27,6 +29,9 @@ bool GLTexture::load_from_file(const std::string& filename, bool generate_mipmap
|
|||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
|
if (!boost::filesystem::exists(filename))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Load a PNG with an alpha channel.
|
// Load a PNG with an alpha channel.
|
||||||
wxImage image;
|
wxImage image;
|
||||||
if (!image.LoadFile(filename, wxBITMAP_TYPE_PNG))
|
if (!image.LoadFile(filename, wxBITMAP_TYPE_PNG))
|
||||||
|
@ -28,6 +28,8 @@ struct MsgDialog : wxDialog
|
|||||||
MsgDialog &operator=(const MsgDialog &) = delete;
|
MsgDialog &operator=(const MsgDialog &) = delete;
|
||||||
virtual ~MsgDialog();
|
virtual ~MsgDialog();
|
||||||
|
|
||||||
|
// TODO: refactor with CreateStdDialogButtonSizer usage
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum {
|
enum {
|
||||||
CONTENT_WIDTH = 500,
|
CONTENT_WIDTH = 500,
|
||||||
|
@ -3,13 +3,16 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <tuple>
|
#include <deque>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include "../../libslic3r/libslic3r.h"
|
#include "../../libslic3r/libslic3r.h"
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
@ -34,7 +37,11 @@ struct Http::priv
|
|||||||
::curl_httppost *form;
|
::curl_httppost *form;
|
||||||
::curl_httppost *form_end;
|
::curl_httppost *form_end;
|
||||||
::curl_slist *headerlist;
|
::curl_slist *headerlist;
|
||||||
|
// Used for reading the body
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
|
// Used for storing file streams added as multipart form parts
|
||||||
|
// Using a deque here because unlike vector it doesn't ivalidate pointers on insertion
|
||||||
|
std::deque<std::ifstream> form_files;
|
||||||
size_t limit;
|
size_t limit;
|
||||||
bool cancel;
|
bool cancel;
|
||||||
|
|
||||||
@ -50,6 +57,10 @@ struct Http::priv
|
|||||||
static size_t writecb(void *data, size_t size, size_t nmemb, void *userp);
|
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(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);
|
static int xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow);
|
||||||
|
static size_t form_file_read_cb(char *buffer, size_t size, size_t nitems, void *userp);
|
||||||
|
|
||||||
|
void form_add_file(const char *name, const fs::path &path, const char* filename);
|
||||||
|
|
||||||
std::string curl_error(CURLcode curlcode);
|
std::string curl_error(CURLcode curlcode);
|
||||||
std::string body_size_error();
|
std::string body_size_error();
|
||||||
void http_perform();
|
void http_perform();
|
||||||
@ -135,6 +146,47 @@ int Http::priv::xfercb_legacy(void *userp, double dltotal, double dlnow, double
|
|||||||
return xfercb(userp, dltotal, dlnow, ultotal, ulnow);
|
return xfercb(userp, dltotal, dlnow, ultotal, ulnow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Http::priv::form_file_read_cb(char *buffer, size_t size, size_t nitems, void *userp)
|
||||||
|
{
|
||||||
|
auto stream = reinterpret_cast<fs::ifstream*>(userp);
|
||||||
|
|
||||||
|
try {
|
||||||
|
stream->read(buffer, size * nitems);
|
||||||
|
} catch (...) {
|
||||||
|
return CURL_READFUNC_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream->gcount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Http::priv::form_add_file(const char *name, const fs::path &path, const char* filename)
|
||||||
|
{
|
||||||
|
// We can't use CURLFORM_FILECONTENT, because curl doesn't support Unicode filenames on Windows
|
||||||
|
// and so we use CURLFORM_STREAM with boost ifstream to read the file.
|
||||||
|
|
||||||
|
if (filename == nullptr) {
|
||||||
|
filename = path.string().c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::ifstream stream(path, std::ios::in | std::ios::binary);
|
||||||
|
stream.seekg(0, std::ios::end);
|
||||||
|
size_t size = stream.tellg();
|
||||||
|
stream.seekg(0);
|
||||||
|
form_files.push_back(std::move(stream));
|
||||||
|
auto stream_ptr = &form_files.back();
|
||||||
|
|
||||||
|
if (filename != nullptr) {
|
||||||
|
::curl_formadd(&form, &form_end,
|
||||||
|
CURLFORM_COPYNAME, name,
|
||||||
|
CURLFORM_FILENAME, filename,
|
||||||
|
CURLFORM_CONTENTTYPE, "application/octet-stream",
|
||||||
|
CURLFORM_STREAM, static_cast<void*>(stream_ptr),
|
||||||
|
CURLFORM_CONTENTSLENGTH, static_cast<long>(size),
|
||||||
|
CURLFORM_END
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string Http::priv::curl_error(CURLcode curlcode)
|
std::string Http::priv::curl_error(CURLcode curlcode)
|
||||||
{
|
{
|
||||||
return (boost::format("%1% (%2%)")
|
return (boost::format("%1% (%2%)")
|
||||||
@ -154,6 +206,7 @@ void Http::priv::http_perform()
|
|||||||
::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
|
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
|
||||||
::curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(this));
|
::curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(this));
|
||||||
|
::curl_easy_setopt(curl, CURLOPT_READFUNCTION, form_file_read_cb);
|
||||||
|
|
||||||
::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
||||||
#if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 32
|
#if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 32
|
||||||
@ -183,14 +236,20 @@ void Http::priv::http_perform()
|
|||||||
|
|
||||||
if (res != CURLE_OK) {
|
if (res != CURLE_OK) {
|
||||||
if (res == CURLE_ABORTED_BY_CALLBACK) {
|
if (res == CURLE_ABORTED_BY_CALLBACK) {
|
||||||
Progress dummyprogress(0, 0, 0, 0);
|
if (cancel) {
|
||||||
bool cancel = true;
|
// The abort comes from the request being cancelled programatically
|
||||||
if (progressfn) { progressfn(dummyprogress, cancel); }
|
Progress dummyprogress(0, 0, 0, 0);
|
||||||
|
bool cancel = true;
|
||||||
|
if (progressfn) { progressfn(dummyprogress, cancel); }
|
||||||
|
} else {
|
||||||
|
// The abort comes from the CURLOPT_READFUNCTION callback, which means reading file failed
|
||||||
|
if (errorfn) { errorfn(std::move(buffer), "Error reading file for file upload", http_status); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (res == CURLE_WRITE_ERROR) {
|
else if (res == CURLE_WRITE_ERROR) {
|
||||||
if (errorfn) { errorfn(std::move(buffer), std::move(body_size_error()), http_status); }
|
if (errorfn) { errorfn(std::move(buffer), body_size_error(), http_status); }
|
||||||
} else {
|
} else {
|
||||||
if (errorfn) { errorfn(std::move(buffer), std::move(curl_error(res)), http_status); }
|
if (errorfn) { errorfn(std::move(buffer), curl_error(res), http_status); }
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if (completefn) {
|
if (completefn) {
|
||||||
@ -265,17 +324,15 @@ Http& Http::form_add(const std::string &name, const std::string &contents)
|
|||||||
return *this;
|
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 fs::path &path)
|
||||||
{
|
{
|
||||||
if (p) {
|
if (p) { p->form_add_file(name.c_str(), path.c_str(), nullptr); }
|
||||||
::curl_formadd(&p->form, &p->form_end,
|
return *this;
|
||||||
CURLFORM_COPYNAME, name.c_str(),
|
}
|
||||||
CURLFORM_FILE, filename.c_str(),
|
|
||||||
CURLFORM_CONTENTTYPE, "application/octet-stream",
|
|
||||||
CURLFORM_END
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Http& Http::form_add_file(const std::string &name, const fs::path &path, const std::string &filename)
|
||||||
|
{
|
||||||
|
if (p) { p->form_add_file(name.c_str(), path.c_str(), filename.c_str()); }
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
@ -16,11 +17,11 @@ private:
|
|||||||
public:
|
public:
|
||||||
struct Progress
|
struct Progress
|
||||||
{
|
{
|
||||||
size_t dltotal;
|
size_t dltotal; // Total bytes to download
|
||||||
size_t dlnow;
|
size_t dlnow; // Bytes downloaded so far
|
||||||
size_t ultotal;
|
size_t ultotal; // Total bytes to upload
|
||||||
size_t ulnow;
|
size_t ulnow; // Bytes uploaded so far
|
||||||
|
|
||||||
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)
|
dltotal(dltotal), dlnow(dlnow), ultotal(ultotal), ulnow(ulnow)
|
||||||
{}
|
{}
|
||||||
@ -33,6 +34,10 @@ public:
|
|||||||
|
|
||||||
Http(Http &&other);
|
Http(Http &&other);
|
||||||
|
|
||||||
|
// Note: strings are expected to be UTF-8-encoded
|
||||||
|
|
||||||
|
// 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 get(std::string url);
|
||||||
static Http post(std::string url);
|
static Http post(std::string url);
|
||||||
~Http();
|
~Http();
|
||||||
@ -41,21 +46,42 @@ public:
|
|||||||
Http& operator=(const Http &) = delete;
|
Http& operator=(const Http &) = delete;
|
||||||
Http& operator=(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);
|
Http& size_limit(size_t sizeLimit);
|
||||||
|
// Sets a HTTP header field.
|
||||||
Http& header(std::string name, const std::string &value);
|
Http& header(std::string name, const std::string &value);
|
||||||
|
// Removes a header field.
|
||||||
Http& remove_header(std::string name);
|
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);
|
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(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, `name` is the name of the part
|
||||||
|
Http& form_add_file(const std::string &name, const boost::filesystem::path &path);
|
||||||
|
// Same as above except also override the file's filename with a custom one
|
||||||
|
Http& form_add_file(const std::string &name, const boost::filesystem::path &path, const std::string &filename);
|
||||||
|
|
||||||
|
// Callback called on HTTP request complete
|
||||||
Http& on_complete(CompleteFn fn);
|
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);
|
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);
|
Http& on_progress(ProgressFn fn);
|
||||||
|
|
||||||
|
// Starts performing the request in a background thread
|
||||||
Ptr perform();
|
Ptr perform();
|
||||||
|
// Starts performing the request on the current thread
|
||||||
void perform_sync();
|
void perform_sync();
|
||||||
|
// Cancels a request in progress
|
||||||
void cancel();
|
void cancel();
|
||||||
|
|
||||||
|
// Tells whether current backend supports seting up a CA file using ca_file()
|
||||||
static bool ca_file_supported();
|
static bool ca_file_supported();
|
||||||
private:
|
private:
|
||||||
Http(const std::string &url);
|
Http(const std::string &url);
|
||||||
|
@ -1,20 +1,65 @@
|
|||||||
#include "OctoPrint.hpp"
|
#include "OctoPrint.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
#include <wx/frame.h>
|
#include <wx/frame.h>
|
||||||
#include <wx/event.h>
|
#include <wx/event.h>
|
||||||
#include <wx/progdlg.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 "libslic3r/PrintConfig.hpp"
|
||||||
#include "slic3r/GUI/GUI.hpp"
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
|
#include "slic3r/GUI/MsgDialog.hpp"
|
||||||
#include "Http.hpp"
|
#include "Http.hpp"
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
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().wstring())),
|
||||||
|
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();
|
||||||
|
wxString stem(path.stem().wstring());
|
||||||
|
txt_filename->SetSelection(0, stem.Length());
|
||||||
|
|
||||||
|
Fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path filename() const {
|
||||||
|
return fs::path(txt_filename->GetValue().wx_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool print() const { return box_print->GetValue(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OctoPrint::OctoPrint(DynamicPrintConfig *config) :
|
OctoPrint::OctoPrint(DynamicPrintConfig *config) :
|
||||||
host(config->opt_string("octoprint_host")),
|
host(config->opt_string("octoprint_host")),
|
||||||
apikey(config->opt_string("octoprint_apikey")),
|
apikey(config->opt_string("octoprint_apikey")),
|
||||||
@ -27,24 +72,39 @@ bool OctoPrint::test(wxString &msg) const
|
|||||||
// it is ok to refer to `msg` from within the closure
|
// it is ok to refer to `msg` from within the closure
|
||||||
|
|
||||||
bool res = true;
|
bool res = true;
|
||||||
|
auto url = make_url("api/version");
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << boost::format("Octoprint: Get version at: %1%") % url;
|
||||||
|
|
||||||
auto url = std::move(make_url("api/version"));
|
|
||||||
auto http = Http::get(std::move(url));
|
auto http = Http::get(std::move(url));
|
||||||
set_auth(http);
|
set_auth(http);
|
||||||
http.on_error([&](std::string, std::string error, unsigned status) {
|
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;
|
res = false;
|
||||||
msg = format_error(error, status);
|
msg = format_error(error, status);
|
||||||
})
|
})
|
||||||
|
.on_complete([&](std::string body, unsigned) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: Got version: %1%") % body;
|
||||||
|
})
|
||||||
.perform_sync();
|
.perform_sync();
|
||||||
|
|
||||||
return res;
|
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 };
|
enum { PROGRESS_RANGE = 1000 };
|
||||||
|
|
||||||
const auto errortitle = _(L("Error while uploading to the OctoPrint server"));
|
const auto errortitle = _(L("Error while uploading to the OctoPrint server"));
|
||||||
|
fs::path filepath(filename);
|
||||||
|
|
||||||
|
SendDialog send_dialog(filepath.filename());
|
||||||
|
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(
|
wxProgressDialog progress_dialog(
|
||||||
_(L("OctoPrint upload")),
|
_(L("OctoPrint upload")),
|
||||||
@ -61,14 +121,26 @@ bool OctoPrint::send_gcode(const std::string &filename, bool print) const
|
|||||||
|
|
||||||
bool res = true;
|
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.string()
|
||||||
|
% url
|
||||||
|
% upload_filename.string()
|
||||||
|
% upload_parent_path.string()
|
||||||
|
% print;
|
||||||
|
|
||||||
|
auto http = Http::post(std::move(url));
|
||||||
set_auth(http);
|
set_auth(http);
|
||||||
http.form_add("print", print ? "true" : "false")
|
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) {
|
.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);
|
progress_dialog.Update(PROGRESS_RANGE);
|
||||||
})
|
})
|
||||||
.on_error([&](std::string body, std::string error, unsigned status) {
|
.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));
|
auto errormsg = wxString::Format("%s: %s", errortitle, format_error(error, status));
|
||||||
GUI::show_error(&progress_dialog, std::move(errormsg));
|
GUI::show_error(&progress_dialog, std::move(errormsg));
|
||||||
res = false;
|
res = false;
|
||||||
@ -102,24 +174,24 @@ std::string OctoPrint::make_url(const std::string &path) const
|
|||||||
{
|
{
|
||||||
if (host.find("http://") == 0 || host.find("https://") == 0) {
|
if (host.find("http://") == 0 || host.find("https://") == 0) {
|
||||||
if (host.back() == '/') {
|
if (host.back() == '/') {
|
||||||
return std::move((boost::format("%1%%2%") % host % path).str());
|
return (boost::format("%1%%2%") % host % path).str();
|
||||||
} else {
|
} else {
|
||||||
return std::move((boost::format("%1%/%2%") % host % path).str());
|
return (boost::format("%1%/%2%") % host % path).str();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return std::move((boost::format("http://%1%/%2%") % host % path).str());
|
return (boost::format("http://%1%/%2%") % host % path).str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString OctoPrint::format_error(std::string error, unsigned status)
|
wxString OctoPrint::format_error(const std::string &error, unsigned status)
|
||||||
{
|
{
|
||||||
const wxString wxerror = error;
|
auto wxerror = wxString::FromUTF8(error.data());
|
||||||
|
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
return wxString::Format("HTTP %u: %s", status,
|
return wxString::Format("HTTP %u: %s", status,
|
||||||
(status == 401 ? _(L("Invalid API key")) : wxerror));
|
(status == 401 ? _(L("Invalid API key")) : wxerror));
|
||||||
} else {
|
} else {
|
||||||
return std::move(wxerror);
|
return wxerror;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@ public:
|
|||||||
OctoPrint(DynamicPrintConfig *config);
|
OctoPrint(DynamicPrintConfig *config);
|
||||||
|
|
||||||
bool test(wxString &curl_msg) const;
|
bool test(wxString &curl_msg) const;
|
||||||
bool send_gcode(const std::string &filename, bool print = false) const;
|
// Send gcode file to octoprint, filename is expected to be in UTF-8
|
||||||
|
bool send_gcode(const std::string &filename) const;
|
||||||
private:
|
private:
|
||||||
std::string host;
|
std::string host;
|
||||||
std::string apikey;
|
std::string apikey;
|
||||||
@ -25,7 +26,7 @@ private:
|
|||||||
|
|
||||||
void set_auth(Http &http) const;
|
void set_auth(Http &http) const;
|
||||||
std::string make_url(const std::string &path) const;
|
std::string make_url(const std::string &path) const;
|
||||||
static wxString format_error(std::string error, unsigned status);
|
static wxString format_error(const std::string &error, unsigned status);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,5 +9,5 @@
|
|||||||
OctoPrint(DynamicPrintConfig *config);
|
OctoPrint(DynamicPrintConfig *config);
|
||||||
~OctoPrint();
|
~OctoPrint();
|
||||||
|
|
||||||
bool send_gcode(std::string filename, bool print = false) const;
|
bool send_gcode(std::string filename) const;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user