Skip to content

Commit

Permalink
Support upload g-code to third-party printers (bambulab#2)
Browse files Browse the repository at this point in the history
* wip

* fix cmake warning

* add UI and config options for Moonraker connection

* wip: copy whole print host UI from PS

* add more needed options

* wip 2

* fix string issue on Mac

* wip3
  • Loading branch information
SoftFever committed Aug 20, 2022
1 parent 159ff85 commit dc5e0ee
Show file tree
Hide file tree
Showing 44 changed files with 5,543 additions and 19 deletions.
22 changes: 22 additions & 0 deletions resources/images/add.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions resources/images/add_copies.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions resources/images/browse.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 19 additions & 1 deletion src/libslic3r/Preset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,13 @@ static std::vector<std::string> s_Preset_printer_options {
"silent_mode",
// BBS
"scan_first_layer", "machine_load_filament_time", "machine_unload_filament_time", "machine_pause_gcode",
"nozzle_type", "auxiliary_fan", "nozzle_volume"
"nozzle_type", "auxiliary_fan", "nozzle_volume",
//SoftFever
"connection_moonraker_url","connection_port", "host_type", "print_host", "printhost_apikey",
"printhost_cafile","printhost_port","printhost_authorization_type",
"printhost_user",
"printhost_password",
"printhost_ssl_ignore_revoke"
};

static std::vector<std::string> s_Preset_sla_print_options {
Expand Down Expand Up @@ -2519,6 +2525,16 @@ static std::vector<std::string> s_PhysicalPrinter_opts {
"preset_name", // temporary option to compatibility with older Slicer
"preset_names",
"printer_technology",
"host_type",
"print_host",
"printhost_apikey",
"printhost_cafile",
"printhost_port",
"printhost_authorization_type",
// HTTP digest authentization (RFC 2617)
"printhost_user",
"printhost_password",
"printhost_ssl_ignore_revoke"
};

const std::vector<std::string>& PhysicalPrinter::printer_options()
Expand Down Expand Up @@ -2682,6 +2698,8 @@ void PhysicalPrinterCollection::load_printers(
// see https://github.com/prusa3d/PrusaSlicer/issues/732
boost::filesystem::path dir = boost::filesystem::absolute(boost::filesystem::path(dir_path) / subdir).make_preferred();
m_dir_path = dir.string();
if(!boost::filesystem::exists(dir))
return;
std::string errors_cummulative;
// Store the loaded printers into a new vector, otherwise the binary search for already existing presets would be broken.
std::deque<PhysicalPrinter> printers_loaded;
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Preset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#define PRESET_SLA_MATERIALS_NAME "sla_materials"

//BBS: iot preset type strings
#define PRESET_IOT_PHYSICAL_PRINTER_TYPE "physical_printer"
#define PRESET_IOT_PRINTER_TYPE "printer"
#define PRESET_IOT_FILAMENT_TYPE "filament"
#define PRESET_IOT_PRINT_TYPE "print"
Expand Down
33 changes: 21 additions & 12 deletions src/libslic3r/PresetBundle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ PresetBundle::PresetBundle()
for (size_t i = 0; i < 1; ++i) {
// The following ugly switch is to avoid printers.preset(0) to return the edited instance, as the 0th default is the current one.
Preset &preset = this->printers.default_preset(i);
for (const char *key : {"printer_settings_id", "printer_model", "printer_variant"}) preset.config.optptr(key, true);
for (const char *key : {"printer_settings_id", "printer_model", "printer_variant","physical_printer_settings_id"}) preset.config.optptr(key, true);
//if (i == 0) {
preset.config.optptr("default_print_profile", true);
preset.config.option<ConfigOptionStrings>("default_filament_profile", true);
Expand Down Expand Up @@ -268,6 +268,11 @@ PresetsConfigSubstitutions PresetBundle::load_presets(AppConfig &config, Forward
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
}
try {
this->physical_printers.load_printers(dir_user_presets, "physical_printer", substitutions, substitution_rule);
} catch (const std::runtime_error &err) {
errors_cummulative += err.what();
}
this->update_multi_material_filament_presets();
this->update_compatible(PresetSelectCompatibleType::Never);
if (! errors_cummulative.empty())
Expand Down Expand Up @@ -532,7 +537,7 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(AppConfig &config, st
// First load the vendor specific system presets.
PresetsConfigSubstitutions substitutions;
std::string errors_cummulative;
bool process_added = false, filament_added = false, machine_added = false;
bool process_added = false, filament_added = false, machine_added = false, physical_printer_added = false;

BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" enter, substitution_rule %1%, preset toltal count %2%")%substitution_rule%my_presets.size();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" print's selected_idx %1%, selected_name %2%") %prints.get_selected_idx() %prints.get_selected_preset_name();
Expand Down Expand Up @@ -562,6 +567,11 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(AppConfig &config, st
preset_collection = &(this->printers);
machine_added |= preset_collection->load_user_preset(name, value_map, substitutions, substitution_rule);
}
else if(type_iter->second == PRESET_IOT_PHYSICAL_PRINTER_TYPE){
preset_collection = &(this->printers);
physical_printer_added |= preset_collection->load_user_preset(name, value_map, substitutions, substitution_rule);

}
else {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("invalid type %1% for setting %2%") %type_iter->second %name;
continue;
Expand Down Expand Up @@ -645,9 +655,6 @@ void PresetBundle::update_system_preset_setting_ids(std::map<std::string, std::m
else if (type_iter->second == PRESET_IOT_PRINTER_TYPE) {
preset_collection = &(this->printers);
}
else if (type_iter->second == PRESET_IOT_PRINTER_TYPE) {
preset_collection = &(this->printers);
}
else {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("invalid type %1% for setting %2%") %type_iter->second %name;
continue;
Expand Down Expand Up @@ -680,7 +687,7 @@ void PresetBundle::update_system_preset_setting_ids(std::map<std::string, std::m
bool PresetBundle::validate_printers(const std::string &name, DynamicPrintConfig& config)
{
// BBS TODO:
#if 0
#if 1
std::vector<std::string> inherits_values;
PrinterTechnology printer_technology = Preset::printer_technology(config);
size_t num_extruders = (printer_technology == ptFFF) ?
Expand Down Expand Up @@ -1177,7 +1184,7 @@ void PresetBundle::export_selections(AppConfig &config)
// BBS
//config.set("presets", "sla_print", sla_prints.get_selected_preset_name());
//config.set("presets", "sla_material", sla_materials.get_selected_preset_name());
//config.set("presets", "physical_printer", physical_printers.get_selected_full_printer_name());
config.set("presets", "physical_printer", physical_printers.get_selected_full_printer_name());
//BBS: add config related log
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": printer %1%, print %2%, filaments[0] %3% ")%printers.get_selected_preset_name() % prints.get_selected_preset_name() %filament_presets[0];
}
Expand Down Expand Up @@ -1245,13 +1252,15 @@ DynamicPrintConfig PresetBundle::full_config() const
DynamicPrintConfig PresetBundle::full_config_secure() const
{
DynamicPrintConfig config = this->full_config();
//BBS example: config.erase("print_host");
return config;
//FIXME legacy, the keys should not be there after conversion to a Physical Printer profile.
config.erase("print_host");
config.erase("printhost_apikey");
config.erase("printhost_cafile"); return config;
}

const std::set<std::string> ignore_settings_list ={
"inherits",
"print_settings_id", "filament_settings_id", "printer_settings_id"
"print_settings_id", "filament_settings_id", "printer_settings_id","physical_printer_settings_id"
};

DynamicPrintConfig PresetBundle::full_fff_config() const
Expand Down Expand Up @@ -1432,6 +1441,7 @@ DynamicPrintConfig PresetBundle::full_fff_config() const
out.option<ConfigOptionStrings>("filament_settings_id", true)->values = this->filament_presets;
out.option<ConfigOptionString >("printer_settings_id", true)->value = this->printers.get_selected_preset_name();
out.option<ConfigOptionStrings>("filament_ids", true)->values = filament_ids;
// out.option<ConfigOptionString >("physical_printer_settings_id", true)->value = this->physical_printers.get_selected_printer_preset_name();
// Serialize the collected "compatible_printers_condition" and "inherits" fields.
// There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored.
// The vector will not be stored if all fields are empty strings.
Expand Down Expand Up @@ -1810,8 +1820,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
this->update_compatible(PresetSelectCompatibleType::Never);

//BBS
//const std::string &physical_printer = config.option<ConfigOptionString>("physical_printer_settings_id", true)->value;
const std::string physical_printer;
const std::string &physical_printer = config.option<ConfigOptionString>("physical_printer_settings_id", true)->value;
if (this->printers.get_edited_preset().is_external || physical_printer.empty()) {
this->physical_printers.unselect_printer();
} else {
Expand Down
134 changes: 134 additions & 0 deletions src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@ static t_config_enum_values s_keys_map_PrinterTechnology {
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrinterTechnology)

static t_config_enum_values s_keys_map_PrintHostType {
{ "prusalink", htPrusaLink },
{ "octoprint", htOctoPrint },
{ "duet", htDuet },
{ "flashair", htFlashAir },
{ "astrobox", htAstroBox },
{ "repetier", htRepetier },
{ "mks", htMKS }
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintHostType)

static t_config_enum_values s_keys_map_AuthorizationType {
{ "key", atKeyPassword },
{ "user", atUserPassword }
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(AuthorizationType)

static t_config_enum_values s_keys_map_GCodeFlavor {
{ "marlin", gcfMarlinLegacy },
{ "reprap", gcfRepRapSprinter },
Expand Down Expand Up @@ -257,6 +274,7 @@ void PrintConfigDef::init_common_params()

def = this->add("printable_area", coPoints);
def->label = L("Printable area");

//BBS
def->mode = comDevelop;
def->set_default_value(new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) });
Expand Down Expand Up @@ -304,6 +322,98 @@ void PrintConfigDef::init_common_params()
def->mode = comDevelop;
def->set_default_value(new ConfigOptionStrings());

//SoftFever
def = this->add("connection_moonraker_url", coString);
def->label = L("Moonraker URL");
//def->tooltip = L("Names of presets related to the physical printer");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString("http://"));

def = this->add("connection_port", coString);
def->label = L("Connection port");
//def->tooltip = L("Names of presets related to the physical printer");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString("7125"));



def = this->add("print_host", coString);
def->label = L("Hostname, IP or URL");
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
"the hostname, IP address or URL of the printer host instance. "
"Print host behind HAProxy with basic auth enabled can be accessed by putting the user name and password into the URL "
"in the following format: https://username:password@your-octopi-address/");
def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionString(""));

def = this->add("printhost_apikey", coString);
def->label = L("API Key / Password");
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
"the API Key or the password required for authentication.");
def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionString(""));

def = this->add("printhost_port", coString);
def->label = L("Printer");
def->tooltip = L("Name of the printer");
def->gui_type = ConfigOptionDef::GUIType::select_open;
def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionString(""));

def = this->add("printhost_cafile", coString);
def->label = L("HTTPS CA File");
def->tooltip = L("Custom CA certificate file can be specified for HTTPS OctoPrint connections, in crt/pem format. "
"If left blank, the default OS CA certificate repository is used.");
def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionString(""));

// Options used by physical printers

def = this->add("printhost_user", coString);
def->label = L("User");
// def->tooltip = L("");
def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionString(""));

def = this->add("printhost_password", coString);
def->label = L("Password");
// def->tooltip = L("");
def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionString(""));

// Only available on Windows.
def = this->add("printhost_ssl_ignore_revoke", coBool);
def->label = L("Ignore HTTPS certificate revocation checks");
def->tooltip = L("Ignore HTTPS certificate revocation checks in case of missing or offline distribution points. "
"One may want to enable this option for self signed certificates if connection fails.");
def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionBool(false));

def = this->add("preset_names", coStrings);
def->label = L("Printer preset names");
def->tooltip = L("Names of presets related to the physical printer");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionStrings());

def = this->add("printhost_authorization_type", coEnum);
def->label = L("Authorization Type");
// def->tooltip = L("");
def->enum_keys_map = &ConfigOptionEnum<AuthorizationType>::get_enum_values();
def->enum_values.push_back("key");
def->enum_values.push_back("user");
def->enum_labels.push_back(L("API key"));
def->enum_labels.push_back(L("HTTP digest"));
def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionEnum<AuthorizationType>(atKeyPassword));

// temporary workaround for compatibility with older Slicer
{
def = this->add("preset_name", coString);
Expand Down Expand Up @@ -1624,6 +1734,30 @@ void PrintConfigDef::init_fff_params()
def->mode = comDevelop;
def->set_default_value(new ConfigOptionFloats { 0.4 });

def = this->add("host_type", coEnum);
def->label = L("Host Type");
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field must contain "
"the kind of the host.");
def->enum_keys_map = &ConfigOptionEnum<PrintHostType>::get_enum_values();
def->enum_values.push_back("prusalink");
def->enum_values.push_back("octoprint");
def->enum_values.push_back("duet");
def->enum_values.push_back("flashair");
def->enum_values.push_back("astrobox");
def->enum_values.push_back("repetier");
def->enum_values.push_back("mks");
def->enum_labels.push_back("PrusaLink");
def->enum_labels.push_back("OctoPrint");
def->enum_labels.push_back("Duet");
def->enum_labels.push_back("FlashAir");
def->enum_labels.push_back("AstroBox");
def->enum_labels.push_back("Repetier");
def->enum_labels.push_back("MKS");
def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli;
def->set_default_value(new ConfigOptionEnum<PrintHostType>(htOctoPrint));


def = this->add("nozzle_volume", coFloat);
def->label = L("Nozzle volume");
def->tooltip = L("Volume of nozzle between the cutter and the end of nozzle");
Expand Down
Loading

0 comments on commit dc5e0ee

Please sign in to comment.