Skip to content

Commit

Permalink
Support for Obico cloud integration (#4116)
Browse files Browse the repository at this point in the history
support obico (#3)

Add printer support for Obico cloud.

---------

Co-authored-by: zzh <[email protected]>
  • Loading branch information
kennethjiang and anjingxw authored Feb 27, 2024
1 parent 047b889 commit 8c941df
Show file tree
Hide file tree
Showing 11 changed files with 519 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ static t_config_enum_values s_keys_map_PrintHostType {
{ "flashair", htFlashAir },
{ "astrobox", htAstroBox },
{ "repetier", htRepetier },
{ "mks", htMKS }
{ "mks", htMKS },
{ "obico", htObico }
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintHostType)

Expand Down Expand Up @@ -3038,6 +3039,7 @@ def = this->add("filament_loading_speed", coFloats);
def->enum_values.push_back("astrobox");
def->enum_values.push_back("repetier");
def->enum_values.push_back("mks");
def->enum_values.push_back("obico");
def->enum_labels.push_back("PrusaLink");
def->enum_labels.push_back("PrusaConnect");
def->enum_labels.push_back("Octo/Klipper");
Expand All @@ -3046,6 +3048,7 @@ def = this->add("filament_loading_speed", coFloats);
def->enum_labels.push_back("AstroBox");
def->enum_labels.push_back("Repetier");
def->enum_labels.push_back("MKS");
def->enum_labels.push_back("Obico");
def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionEnum<PrintHostType>(htOctoPrint));
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/PrintConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ enum class FuzzySkinType {
};

enum PrintHostType {
htPrusaLink, htPrusaConnect, htOctoPrint, htDuet, htFlashAir, htAstroBox, htRepetier, htMKS
htPrusaLink, htPrusaConnect, htOctoPrint, htDuet, htFlashAir, htAstroBox, htRepetier, htMKS, htObico
};

enum AuthorizationType {
Expand Down
4 changes: 4 additions & 0 deletions src/slic3r/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,10 @@ set(SLIC3R_GUI_SOURCES
GUI/calib_dlg.cpp
Utils/CalibUtils.cpp
Utils/CalibUtils.hpp
GUI/PrinterCloudAuthDialog.cpp
GUI/PrinterCloudAuthDialog.hpp
Utils/Obico.cpp
Utils/Obico.hpp
)

if (WIN32)
Expand Down
77 changes: 77 additions & 0 deletions src/slic3r/GUI/PhysicalPrinterDialog.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#include "PhysicalPrinterDialog.hpp"
#include "PresetComboBoxes.hpp"
#include "PrinterCloudAuthDialog.hpp"

#include <cstddef>
#include <vector>
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>

#include <wx/sizer.h>
#include <wx/stattext.h>
Expand Down Expand Up @@ -124,6 +126,8 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
this->update();
if (opt_key == "print_host")
this->update_printhost_buttons();
if (opt_key == "printhost_port")
this->update_ports();
};

m_optgroup->append_single_option_line("host_type");
Expand Down Expand Up @@ -161,12 +165,31 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
show_error(this, text);
return;
}

wxString msg;
bool result;
{
// Show a wait cursor during the connection test, as it is blocking UI.
wxBusyCursor wait;
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)
show_info(this, host->get_test_ok_msg(), _L("Success!"));
Expand Down Expand Up @@ -311,6 +334,42 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
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()
{
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
Expand Down Expand Up @@ -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") {
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
m_optgroup->show_field("printhost_authorization_type");
Expand All @@ -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 {
m_optgroup->set_value("host_type", int(PrintHostType::htOctoPrint), false);
Expand Down
1 change: 1 addition & 0 deletions src/slic3r/GUI/PhysicalPrinterDialog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class PhysicalPrinterDialog : public DPIDialog
void update_preset_input();
void update_printhost_buttons();
void update_printers();
void update_ports();

protected:
void on_dpi_changed(const wxRect& suggested_rect) override;
Expand Down
105 changes: 105 additions & 0 deletions src/slic3r/GUI/PrinterCloudAuthDialog.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 51 additions & 0 deletions src/slic3r/GUI/PrinterCloudAuthDialog.hpp
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 8c941df

Please sign in to comment.