mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-14 10:17:55 -06:00
Support for Obico cloud integration (#4116)
support obico (#3) Add printer support for Obico cloud. --------- Co-authored-by: zzh <anjingxw@126.com>
This commit is contained in:
parent
047b889ba6
commit
8c941df4e8
11 changed files with 519 additions and 2 deletions
|
@ -102,7 +102,8 @@ static t_config_enum_values s_keys_map_PrintHostType {
|
||||||
{ "flashair", htFlashAir },
|
{ "flashair", htFlashAir },
|
||||||
{ "astrobox", htAstroBox },
|
{ "astrobox", htAstroBox },
|
||||||
{ "repetier", htRepetier },
|
{ "repetier", htRepetier },
|
||||||
{ "mks", htMKS }
|
{ "mks", htMKS },
|
||||||
|
{ "obico", htObico }
|
||||||
};
|
};
|
||||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintHostType)
|
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintHostType)
|
||||||
|
|
||||||
|
@ -3038,6 +3039,7 @@ def = this->add("filament_loading_speed", coFloats);
|
||||||
def->enum_values.push_back("astrobox");
|
def->enum_values.push_back("astrobox");
|
||||||
def->enum_values.push_back("repetier");
|
def->enum_values.push_back("repetier");
|
||||||
def->enum_values.push_back("mks");
|
def->enum_values.push_back("mks");
|
||||||
|
def->enum_values.push_back("obico");
|
||||||
def->enum_labels.push_back("PrusaLink");
|
def->enum_labels.push_back("PrusaLink");
|
||||||
def->enum_labels.push_back("PrusaConnect");
|
def->enum_labels.push_back("PrusaConnect");
|
||||||
def->enum_labels.push_back("Octo/Klipper");
|
def->enum_labels.push_back("Octo/Klipper");
|
||||||
|
@ -3046,6 +3048,7 @@ def = this->add("filament_loading_speed", coFloats);
|
||||||
def->enum_labels.push_back("AstroBox");
|
def->enum_labels.push_back("AstroBox");
|
||||||
def->enum_labels.push_back("Repetier");
|
def->enum_labels.push_back("Repetier");
|
||||||
def->enum_labels.push_back("MKS");
|
def->enum_labels.push_back("MKS");
|
||||||
|
def->enum_labels.push_back("Obico");
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->cli = ConfigOptionDef::nocli;
|
def->cli = ConfigOptionDef::nocli;
|
||||||
def->set_default_value(new ConfigOptionEnum<PrintHostType>(htOctoPrint));
|
def->set_default_value(new ConfigOptionEnum<PrintHostType>(htOctoPrint));
|
||||||
|
|
|
@ -59,7 +59,7 @@ enum class FuzzySkinType {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PrintHostType {
|
enum PrintHostType {
|
||||||
htPrusaLink, htPrusaConnect, htOctoPrint, htDuet, htFlashAir, htAstroBox, htRepetier, htMKS
|
htPrusaLink, htPrusaConnect, htOctoPrint, htDuet, htFlashAir, htAstroBox, htRepetier, htMKS, htObico
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AuthorizationType {
|
enum AuthorizationType {
|
||||||
|
|
|
@ -524,6 +524,10 @@ set(SLIC3R_GUI_SOURCES
|
||||||
GUI/calib_dlg.cpp
|
GUI/calib_dlg.cpp
|
||||||
Utils/CalibUtils.cpp
|
Utils/CalibUtils.cpp
|
||||||
Utils/CalibUtils.hpp
|
Utils/CalibUtils.hpp
|
||||||
|
GUI/PrinterCloudAuthDialog.cpp
|
||||||
|
GUI/PrinterCloudAuthDialog.hpp
|
||||||
|
Utils/Obico.cpp
|
||||||
|
Utils/Obico.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
#include "PhysicalPrinterDialog.hpp"
|
#include "PhysicalPrinterDialog.hpp"
|
||||||
#include "PresetComboBoxes.hpp"
|
#include "PresetComboBoxes.hpp"
|
||||||
|
#include "PrinterCloudAuthDialog.hpp"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
#include <wx/stattext.h>
|
#include <wx/stattext.h>
|
||||||
|
@ -124,6 +126,8 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
|
||||||
this->update();
|
this->update();
|
||||||
if (opt_key == "print_host")
|
if (opt_key == "print_host")
|
||||||
this->update_printhost_buttons();
|
this->update_printhost_buttons();
|
||||||
|
if (opt_key == "printhost_port")
|
||||||
|
this->update_ports();
|
||||||
};
|
};
|
||||||
|
|
||||||
m_optgroup->append_single_option_line("host_type");
|
m_optgroup->append_single_option_line("host_type");
|
||||||
|
@ -161,12 +165,31 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
|
||||||
show_error(this, text);
|
show_error(this, text);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString msg;
|
wxString msg;
|
||||||
bool result;
|
bool result;
|
||||||
{
|
{
|
||||||
// Show a wait cursor during the connection test, as it is blocking UI.
|
// Show a wait cursor during the connection test, as it is blocking UI.
|
||||||
wxBusyCursor wait;
|
wxBusyCursor wait;
|
||||||
result = host->test(msg);
|
result = host->test(msg);
|
||||||
|
|
||||||
|
if (!result && host->is_cloud()) {
|
||||||
|
PrinterCloudAuthDialog dlg(this->GetParent(), host.get());
|
||||||
|
dlg.ShowModal();
|
||||||
|
|
||||||
|
auto api_key = dlg.GetApiKey();
|
||||||
|
m_config->opt_string("printhost_apikey") = api_key;
|
||||||
|
result = !api_key.empty();
|
||||||
|
if (result) {
|
||||||
|
if (Field* print_host_webui_field = this->m_optgroup->get_field("printhost_apikey"); print_host_webui_field) {
|
||||||
|
if (TextInput* temp_input = dynamic_cast<TextInput*>(print_host_webui_field->getWindow()); temp_input) {
|
||||||
|
if (wxTextCtrl* temp = temp_input->GetTextCtrl()) {
|
||||||
|
temp->SetValue(wxString(api_key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (result)
|
if (result)
|
||||||
show_info(this, host->get_test_ok_msg(), _L("Success!"));
|
show_info(this, host->get_test_ok_msg(), _L("Success!"));
|
||||||
|
@ -311,6 +334,42 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicalPrinterDialog::update_ports() {
|
||||||
|
const PrinterTechnology tech = Preset::printer_technology(*m_config);
|
||||||
|
if (tech == ptFFF) {
|
||||||
|
const auto opt = m_config->option<ConfigOptionEnum<PrintHostType>>("host_type");
|
||||||
|
if (opt->value == htObico) {
|
||||||
|
auto build_web_ui = [](DynamicPrintConfig* config) {
|
||||||
|
auto host = config->opt_string("print_host");
|
||||||
|
auto port = config->opt_string("printhost_port");
|
||||||
|
auto api_key = config->opt_string("printhost_apikey");
|
||||||
|
if (host.empty() || port.empty()) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
boost::regex re("\\[(\\d+)\\]");
|
||||||
|
boost::smatch match;
|
||||||
|
if (!boost::regex_search(port, match, re))
|
||||||
|
return std::string();
|
||||||
|
if (match.size() <= 1) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
boost::format urlFormat("%1%/printers/%2%/control");
|
||||||
|
urlFormat % host % match[1];
|
||||||
|
return urlFormat.str();
|
||||||
|
};
|
||||||
|
auto url = build_web_ui(m_config);
|
||||||
|
if (Field* print_host_webui_field = m_optgroup->get_field("print_host_webui"); print_host_webui_field) {
|
||||||
|
if (TextInput* temp_input = dynamic_cast<TextInput*>(print_host_webui_field->getWindow()); temp_input) {
|
||||||
|
if (wxTextCtrl* temp = temp_input->GetTextCtrl()) {
|
||||||
|
temp->SetValue(wxString(url));
|
||||||
|
m_config->opt_string("print_host_webui") = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PhysicalPrinterDialog::update_printhost_buttons()
|
void PhysicalPrinterDialog::update_printhost_buttons()
|
||||||
{
|
{
|
||||||
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
|
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
|
||||||
|
@ -415,6 +474,12 @@ void PhysicalPrinterDialog::update(bool printer_change)
|
||||||
if (wxTextCtrl* temp = dynamic_cast<wxTextCtrl*>(printhost_field->getWindow()); temp && temp->GetValue() == L"https://connect.prusa3d.com") {
|
if (wxTextCtrl* temp = dynamic_cast<wxTextCtrl*>(printhost_field->getWindow()); temp && temp->GetValue() == L"https://connect.prusa3d.com") {
|
||||||
temp->SetValue(wxString());
|
temp->SetValue(wxString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TextInput* temp_input = dynamic_cast<TextInput*>(printhost_field->getWindow()); temp_input) {
|
||||||
|
if (wxTextCtrl* temp = temp_input->GetTextCtrl(); temp &&temp->GetValue() == L"https://app.obico.io") {
|
||||||
|
temp->SetValue(wxString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (opt->value == htPrusaLink) { // PrusaConnect does NOT allow http digest
|
if (opt->value == htPrusaLink) { // PrusaConnect does NOT allow http digest
|
||||||
m_optgroup->show_field("printhost_authorization_type");
|
m_optgroup->show_field("printhost_authorization_type");
|
||||||
|
@ -436,6 +501,18 @@ void PhysicalPrinterDialog::update(bool printer_change)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opt->value == htObico) {
|
||||||
|
supports_multiple_printers = true;
|
||||||
|
if (Field* printhost_field = m_optgroup->get_field("print_host"); printhost_field) {
|
||||||
|
if (TextInput* temp_input = dynamic_cast<TextInput*>(printhost_field->getWindow()); temp_input) {
|
||||||
|
if (wxTextCtrl* temp = temp_input->GetTextCtrl(); temp && temp->GetValue().IsEmpty()) {
|
||||||
|
temp->SetValue(L"https://app.obico.io");
|
||||||
|
m_config->opt_string("print_host") = "https://app.obico.io";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_optgroup->set_value("host_type", int(PrintHostType::htOctoPrint), false);
|
m_optgroup->set_value("host_type", int(PrintHostType::htOctoPrint), false);
|
||||||
|
|
|
@ -61,6 +61,7 @@ public:
|
||||||
void update_preset_input();
|
void update_preset_input();
|
||||||
void update_printhost_buttons();
|
void update_printhost_buttons();
|
||||||
void update_printers();
|
void update_printers();
|
||||||
|
void update_ports();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void on_dpi_changed(const wxRect& suggested_rect) override;
|
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||||
|
|
105
src/slic3r/GUI/PrinterCloudAuthDialog.cpp
Normal file
105
src/slic3r/GUI/PrinterCloudAuthDialog.cpp
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
#include "PrinterCloudAuthDialog.hpp"
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/toolbar.h>
|
||||||
|
#include <wx/textdlg.h>
|
||||||
|
|
||||||
|
#include <wx/wx.h>
|
||||||
|
#include <wx/fileconf.h>
|
||||||
|
#include <wx/file.h>
|
||||||
|
#include <wx/wfstream.h>
|
||||||
|
|
||||||
|
#include <boost/cast.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include "MainFrame.hpp"
|
||||||
|
#include <boost/dll.hpp>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <slic3r/GUI/Widgets/WebView.hpp>
|
||||||
|
//------------------------------------------
|
||||||
|
// PrinterCloundAuthDialog
|
||||||
|
//------------------------------------------
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
PrinterCloudAuthDialog::PrinterCloudAuthDialog(wxWindow* parent, PrintHost* host)
|
||||||
|
: wxDialog((wxWindow*) (wxGetApp().mainframe), wxID_ANY, "Login"), m_host(host)
|
||||||
|
{
|
||||||
|
SetBackgroundColour(*wxWHITE);
|
||||||
|
// Url
|
||||||
|
host->get_login_url(m_TargetUrl);
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "login url = " << m_TargetUrl.ToStdString();
|
||||||
|
|
||||||
|
// Create the webview
|
||||||
|
m_browser = WebView::CreateWebView(this, m_TargetUrl);
|
||||||
|
if (m_browser == nullptr) {
|
||||||
|
wxLogError("Could not init m_browser");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_browser->Hide();
|
||||||
|
m_browser->SetSize(0, 0);
|
||||||
|
|
||||||
|
// Connect the webview events
|
||||||
|
Bind(wxEVT_WEBVIEW_NAVIGATING, &PrinterCloudAuthDialog::OnNavigationRequest, this, m_browser->GetId());
|
||||||
|
Bind(wxEVT_WEBVIEW_NAVIGATED, &PrinterCloudAuthDialog::OnNavigationComplete, this, m_browser->GetId());
|
||||||
|
Bind(wxEVT_WEBVIEW_LOADED, &PrinterCloudAuthDialog::OnDocumentLoaded, this, m_browser->GetId());
|
||||||
|
Bind(wxEVT_WEBVIEW_NEWWINDOW, &PrinterCloudAuthDialog::OnNewWindow, this, m_browser->GetId());
|
||||||
|
Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &PrinterCloudAuthDialog::OnScriptMessage, this, m_browser->GetId());
|
||||||
|
|
||||||
|
// UI
|
||||||
|
SetTitle(_L("Login"));
|
||||||
|
// Set a more sensible size for web browsing
|
||||||
|
wxSize pSize = FromDIP(wxSize(650, 840));
|
||||||
|
SetSize(pSize);
|
||||||
|
|
||||||
|
int screenheight = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y, NULL);
|
||||||
|
int screenwidth = wxSystemSettings::GetMetric(wxSYS_SCREEN_X, NULL);
|
||||||
|
int MaxY = (screenheight - pSize.y) > 0 ? (screenheight - pSize.y) / 2 : 0;
|
||||||
|
wxPoint tmpPT((screenwidth - pSize.x) / 2, MaxY);
|
||||||
|
Move(tmpPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrinterCloudAuthDialog::~PrinterCloudAuthDialog() {}
|
||||||
|
|
||||||
|
void PrinterCloudAuthDialog::OnNavigationRequest(wxWebViewEvent& evt)
|
||||||
|
{
|
||||||
|
//todo
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrinterCloudAuthDialog::OnNavigationComplete(wxWebViewEvent& evt)
|
||||||
|
{
|
||||||
|
m_browser->Show();
|
||||||
|
Layout();
|
||||||
|
//fortest
|
||||||
|
//WebView::RunScript(m_browser, "window.wx.postMessage('This is a web message')");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrinterCloudAuthDialog::OnDocumentLoaded(wxWebViewEvent& evt)
|
||||||
|
{
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrinterCloudAuthDialog::OnNewWindow(wxWebViewEvent& evt) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrinterCloudAuthDialog::OnScriptMessage(wxWebViewEvent& evt)
|
||||||
|
{
|
||||||
|
wxString str_input = evt.GetString();
|
||||||
|
try {
|
||||||
|
json j = json::parse(into_u8(str_input));
|
||||||
|
wxString strCmd = j["command"];
|
||||||
|
if (strCmd == "login_token") {
|
||||||
|
auto token = j["data"]["token"];
|
||||||
|
m_host->set_api_key(token);
|
||||||
|
m_apikey = token;
|
||||||
|
}
|
||||||
|
Close();
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
wxMessageBox(e.what(), "parse json failed", wxICON_WARNING);
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace Slic3r::GUI
|
51
src/slic3r/GUI/PrinterCloudAuthDialog.hpp
Normal file
51
src/slic3r/GUI/PrinterCloudAuthDialog.hpp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef slic3r_GUI_PrinterCloudAuthDialog_hpp_
|
||||||
|
#define slic3r_GUI_PrinterCloudAuthDialog_hpp_
|
||||||
|
|
||||||
|
#include <wx/wx.h>
|
||||||
|
#include <wx/font.h>
|
||||||
|
#include <wx/colour.h>
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/dialog.h>
|
||||||
|
#include "wx/webview.h"
|
||||||
|
|
||||||
|
#if wxUSE_WEBVIEW_IE
|
||||||
|
#include "wx/msw/webview_ie.h"
|
||||||
|
#endif
|
||||||
|
#if wxUSE_WEBVIEW_EDGE
|
||||||
|
#include "wx/msw/webview_edge.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "GUI_Utils.hpp"
|
||||||
|
#include "PrintHost.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
class PrinterCloudAuthDialog : public wxDialog
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
wxWebView* m_browser;
|
||||||
|
wxString m_TargetUrl;
|
||||||
|
|
||||||
|
wxString m_javascript;
|
||||||
|
wxString m_response_js;
|
||||||
|
PrintHost* m_host;
|
||||||
|
std::string m_apikey;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PrinterCloudAuthDialog(wxWindow* parent, PrintHost* host);
|
||||||
|
~PrinterCloudAuthDialog();
|
||||||
|
|
||||||
|
std::string GetApiKey() { return m_apikey; };
|
||||||
|
|
||||||
|
void OnNavigationRequest(wxWebViewEvent& evt);
|
||||||
|
void OnNavigationComplete(wxWebViewEvent& evt);
|
||||||
|
void OnDocumentLoaded(wxWebViewEvent& evt);
|
||||||
|
void OnNewWindow(wxWebViewEvent& evt);
|
||||||
|
void OnScriptMessage(wxWebViewEvent& evt);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // namespace Slic3r::GUI
|
||||||
|
|
||||||
|
#endif
|
218
src/slic3r/Utils/Obico.cpp
Normal file
218
src/slic3r/Utils/Obico.cpp
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
#include "Obico.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
#include <exception>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/algorithm/string/split.hpp>
|
||||||
|
#include <boost/nowide/convert.hpp>
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <wx/progdlg.h>
|
||||||
|
|
||||||
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
|
#include "slic3r/GUI/I18N.hpp"
|
||||||
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
|
#include "slic3r/GUI/format.hpp"
|
||||||
|
#include "Http.hpp"
|
||||||
|
#include "libslic3r/AppConfig.hpp"
|
||||||
|
#include "Bonjour.hpp"
|
||||||
|
#include "slic3r/GUI/BonjourDialog.hpp"
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
namespace pt = boost::property_tree;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
Obico::Obico(DynamicPrintConfig* config) :
|
||||||
|
m_host(config->opt_string("print_host")),
|
||||||
|
m_web_ui(config->opt_string("print_host_webui")),
|
||||||
|
m_cafile(config->opt_string("printhost_cafile")),
|
||||||
|
m_port(config->opt_string("printhost_port")),
|
||||||
|
m_apikey(config->opt_string("printhost_apikey")),
|
||||||
|
m_ssl_revoke_best_effort(config->opt_bool("printhost_ssl_ignore_revoke"))
|
||||||
|
{}
|
||||||
|
|
||||||
|
const char* Obico::get_name() const { return "Obico"; }
|
||||||
|
|
||||||
|
void Obico::set_api_key(const std::string auth_api_key) { m_apikey = auth_api_key; }
|
||||||
|
|
||||||
|
std::string Obico::get_host() const {
|
||||||
|
return m_host;
|
||||||
|
}
|
||||||
|
void Obico::set_auth(Http& http) const
|
||||||
|
{
|
||||||
|
http.header("Authorization", "Bearer " + m_apikey);
|
||||||
|
if (!m_cafile.empty()) {
|
||||||
|
http.ca_file(m_cafile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Obico::get_login_url(wxString& auth_url) const
|
||||||
|
{
|
||||||
|
auth_url = make_url("o/authorize?response_type=token&client_id=OrcaSlicer&hide_navbar=true");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString Obico::get_test_ok_msg() const { return _(L("Connected to Obico successfully!")); }
|
||||||
|
|
||||||
|
wxString Obico::get_test_failed_msg(wxString& msg) const
|
||||||
|
{
|
||||||
|
return GUI::format_wxstr("%s: %s", _L("Could not connect to Obico"), msg.Truncate(256));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Obico::test(wxString& msg) const
|
||||||
|
{
|
||||||
|
if (m_apikey.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool res = true;
|
||||||
|
const char* name = get_name();
|
||||||
|
auto url = make_url("api/v1/version/");
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
|
||||||
|
// Here we do not have to add custom "Host" header - the url contains host filled by user and libCurl will set the header by itself.
|
||||||
|
auto http = Http::get(std::move(url));
|
||||||
|
set_auth(http);
|
||||||
|
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status %
|
||||||
|
body;
|
||||||
|
res = false;
|
||||||
|
msg = format_error(body, error, status);
|
||||||
|
})
|
||||||
|
.on_complete([&, this](std::string body, unsigned) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got version: %2%") % name % body;
|
||||||
|
})
|
||||||
|
#ifdef WIN32
|
||||||
|
.ssl_revoke_best_effort(m_ssl_revoke_best_effort)
|
||||||
|
.on_ip_resolve([&](std::string address) {
|
||||||
|
// Workaround for Windows 10/11 mDNS resolve issue, where two mDNS resolves in succession fail.
|
||||||
|
// Remember resolved address to be reused at successive REST API call.
|
||||||
|
msg = GUI::from_u8(address);
|
||||||
|
})
|
||||||
|
#endif // WIN32
|
||||||
|
.perform_sync();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Obico::get_printers(wxArrayString& printers) const
|
||||||
|
{
|
||||||
|
const char* name = get_name();
|
||||||
|
bool res = false;
|
||||||
|
auto url = make_url("api/v1/printers/");
|
||||||
|
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: List printers at: %2%") % name % url;
|
||||||
|
|
||||||
|
auto http = Http::get(std::move(url));
|
||||||
|
set_auth(http);
|
||||||
|
|
||||||
|
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error listing printers: %2%, HTTP %3%, body: `%4%`") % name % error % status %
|
||||||
|
body;
|
||||||
|
})
|
||||||
|
.on_complete([&](std::string body, unsigned http_status) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got printers: %2%, HTTP status: %3%") % name % body % http_status;
|
||||||
|
if (http_status != 200)
|
||||||
|
throw HostNetworkError(GUI::format(_L("HTTP status: %1%\nMessage body: \"%2%\""), http_status, body));
|
||||||
|
|
||||||
|
std::stringstream ss(body);
|
||||||
|
pt::ptree ptree;
|
||||||
|
try {
|
||||||
|
pt::read_json(ss, ptree);
|
||||||
|
} catch (const pt::ptree_error& err) {
|
||||||
|
throw HostNetworkError(
|
||||||
|
GUI::format(_L("Parsing of host response failed.\nMessage body: \"%1%\"\nError: \"%2%\""), body, err.what()));
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto error = ptree.get_optional<std::string>("error");
|
||||||
|
if (error)
|
||||||
|
throw HostNetworkError(*error);
|
||||||
|
|
||||||
|
try {
|
||||||
|
BOOST_FOREACH (boost::property_tree::ptree::value_type& v, ptree) {
|
||||||
|
const auto name = v.second.get<std::string>("name");
|
||||||
|
const auto port = v.second.get<std::string>("id");
|
||||||
|
printers.push_back(Slic3r::GUI::from_u8(name + " [" + port + "]"));
|
||||||
|
}
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
throw HostNetworkError(
|
||||||
|
GUI::format(_L("Enumeration of host printers failed.\nMessage body: \"%1%\"\nError: \"%2%\""), body, err.what()));
|
||||||
|
}
|
||||||
|
res = true;
|
||||||
|
})
|
||||||
|
.perform_sync();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintHostPostUploadActions Obico::get_post_upload_actions() const {
|
||||||
|
return PrintHostPostUploadAction::StartPrint;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Obico::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const
|
||||||
|
{
|
||||||
|
const char* name = get_name();
|
||||||
|
const auto upload_filename = upload_data.upload_path.filename();
|
||||||
|
const auto upload_parent_path = upload_data.upload_path.parent_path();
|
||||||
|
wxString test_msg;
|
||||||
|
if (!test(test_msg)) {
|
||||||
|
error_fn(std::move(test_msg));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool res = true;
|
||||||
|
auto url = make_url("api/v1/g_code_files/");
|
||||||
|
|
||||||
|
auto http = Http::post(url); // std::move(url));
|
||||||
|
set_auth(http);
|
||||||
|
http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
|
||||||
|
.form_add("path", upload_parent_path.string()) // XXX: slashes on windows ???
|
||||||
|
.form_add("printer_id", m_port)
|
||||||
|
.form_add("filename", upload_filename.string())
|
||||||
|
.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
|
||||||
|
|
||||||
|
.on_complete([&](std::string body, unsigned status) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body;
|
||||||
|
})
|
||||||
|
.on_error([&](std::string body, std::string error, unsigned status) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file to %2%: %3%, HTTP %4%, body: `%5%`") % name % url % error %
|
||||||
|
status % body;
|
||||||
|
error_fn(format_error(body, error, status));
|
||||||
|
res = false;
|
||||||
|
})
|
||||||
|
.on_progress([&](Http::Progress progress, bool& cancel) {
|
||||||
|
prorgess_fn(std::move(progress), cancel);
|
||||||
|
if (cancel) {
|
||||||
|
// Upload was canceled
|
||||||
|
BOOST_LOG_TRIVIAL(info) << name << ": Upload canceled";
|
||||||
|
res = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
#ifdef WIN32
|
||||||
|
.ssl_revoke_best_effort(m_ssl_revoke_best_effort)
|
||||||
|
#endif
|
||||||
|
.perform_sync();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Obico::make_url(const std::string& path) const
|
||||||
|
{
|
||||||
|
if (m_host.find("http://") == 0 || m_host.find("https://") == 0) {
|
||||||
|
if (m_host.back() == '/') {
|
||||||
|
return (boost::format("%1%%2%") % m_host % path).str();
|
||||||
|
} else {
|
||||||
|
return (boost::format("%1%/%2%") % m_host % path).str();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (boost::format("http://%1%/%2%") % m_host % path).str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
src/slic3r/Utils/Obico.hpp
Normal file
51
src/slic3r/Utils/Obico.hpp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef slic3r_Obico_hpp_
|
||||||
|
#define slic3r_Obico_hpp_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <boost/asio/ip/address.hpp>
|
||||||
|
|
||||||
|
#include "PrintHost.hpp"
|
||||||
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class DynamicPrintConfig;
|
||||||
|
class Http;
|
||||||
|
class Obico : public PrintHost
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Obico(DynamicPrintConfig* config);
|
||||||
|
~Obico() override = default;
|
||||||
|
|
||||||
|
const char* get_name() const override;
|
||||||
|
virtual bool can_test() const { return true; };
|
||||||
|
bool has_auto_discovery() const override { return false; }
|
||||||
|
bool is_cloud() const override { return true; }
|
||||||
|
bool get_login_url(wxString& auth_url) const override;
|
||||||
|
void set_api_key(const std::string auth_api_key) override;
|
||||||
|
std::string get_host() const override;
|
||||||
|
|
||||||
|
wxString get_test_ok_msg() const override;
|
||||||
|
wxString get_test_failed_msg(wxString& msg) const override;
|
||||||
|
virtual bool test(wxString& curl_msg) const override;
|
||||||
|
bool get_printers(wxArrayString& printers) const override;
|
||||||
|
PrintHostPostUploadActions get_post_upload_actions() const;
|
||||||
|
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn, InfoFn info_fn) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void set_auth(Http& http) const;
|
||||||
|
private:
|
||||||
|
std::string m_host;
|
||||||
|
std::string m_port;
|
||||||
|
std::string m_apikey;
|
||||||
|
std::string m_cafile;
|
||||||
|
std::string m_web_ui;
|
||||||
|
bool m_ssl_revoke_best_effort;
|
||||||
|
|
||||||
|
std::string make_url(const std::string& path) const;
|
||||||
|
};
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
#endif
|
|
@ -20,6 +20,7 @@
|
||||||
#include "Repetier.hpp"
|
#include "Repetier.hpp"
|
||||||
#include "MKS.hpp"
|
#include "MKS.hpp"
|
||||||
#include "../GUI/PrintHostDialogs.hpp"
|
#include "../GUI/PrintHostDialogs.hpp"
|
||||||
|
#include "Obico.hpp"
|
||||||
|
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
|
@ -54,6 +55,7 @@ PrintHost* PrintHost::get_print_host(DynamicPrintConfig *config)
|
||||||
case htPrusaLink: return new PrusaLink(config);
|
case htPrusaLink: return new PrusaLink(config);
|
||||||
case htPrusaConnect: return new PrusaConnect(config);
|
case htPrusaConnect: return new PrusaConnect(config);
|
||||||
case htMKS: return new MKS(config);
|
case htMKS: return new MKS(config);
|
||||||
|
case htObico: return new Obico(config);
|
||||||
default: return nullptr;
|
default: return nullptr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -70,6 +70,11 @@ public:
|
||||||
|
|
||||||
static PrintHost* get_print_host(DynamicPrintConfig *config);
|
static PrintHost* get_print_host(DynamicPrintConfig *config);
|
||||||
|
|
||||||
|
//Support for cloud webui login
|
||||||
|
virtual bool is_cloud() const { return false; }
|
||||||
|
virtual bool get_login_url(wxString& auth_url) const { return false; }
|
||||||
|
virtual void set_api_key(const std::string auth_api_key) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual wxString format_error(const std::string &body, const std::string &error, unsigned status) const;
|
virtual wxString format_error(const std::string &body, const std::string &error, unsigned status) const;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue