ENH: custom filament sync with printer

1. prompt sync user presets when create custom filament
2. Fix the issue of not displaying printers when creating custom Filaments based on presets when selecting PLA Aero Type.
3. Optimizing the traversal logic during AMS Setting Pop up reduces time complexity and allows for quick pop ups. Additionally, using nozzle calibers for retrieval and repairing custom materials may result in inaccurate retrieval.
4. Implement synchronization logic with the printer
	-a. Received slot information, reset the slot when the "filament_id" in the information does not exist in Studio
	-b. Received slot information, the nozzle temperature in the information is different from the preset nozzle temperature in Studio, reset the current temperature.

Jira: none

Change-Id: I511dc82563ec77a341839671d398607048ce1985
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
This commit is contained in:
maosheng.wei 2024-01-31 18:18:41 +08:00 committed by Lane.Wei
parent d75e79c2ec
commit 626e2a9f79
6 changed files with 169 additions and 83 deletions

View File

@ -2221,6 +2221,10 @@ std::map<std::string, std::vector<Preset const *>> PresetCollection::get_filamen
{ {
std::map<std::string, std::vector<Preset const *>> filament_presets; std::map<std::string, std::vector<Preset const *>> filament_presets;
for (auto &preset : m_presets) { for (auto &preset : m_presets) {
if (preset.is_user()) {
if (preset.inherits() == "") { filament_presets[preset.filament_id].push_back(&preset); }
continue;
}
if (get_preset_base(preset) == &preset) { filament_presets[preset.filament_id].push_back(&preset); } if (get_preset_base(preset) == &preset) { filament_presets[preset.filament_id].push_back(&preset); }
} }
return filament_presets; return filament_presets;

View File

@ -1826,6 +1826,28 @@ void PresetBundle::set_calibrate_printer(std::string name)
} }
} }
std::set<std::string> PresetBundle::get_printer_names_by_printer_type_and_nozzle(const std::string &printer_type, const std::string &nozzle_diameter_str)
{
std::set<std::string> printer_names;
std::ostringstream stream;
for (auto printer_it = this->printers.begin(); printer_it != this->printers.end(); printer_it++) {
if (!printer_it->is_system) continue;
ConfigOption * printer_model_opt = printer_it->config.option("printer_model");
ConfigOptionString *printer_model_str = dynamic_cast<ConfigOptionString *>(printer_model_opt);
if (!printer_model_str) continue;
// use printer_model as printer type
if (printer_model_str->value != printer_type) continue;
if (printer_it->name.find(nozzle_diameter_str) != std::string::npos) printer_names.insert(printer_it->name);
}
assert(printer_names.size() == 1);
return printer_names;
}
//BBS: check whether this is the only edited filament //BBS: check whether this is the only edited filament
bool PresetBundle::is_the_only_edited_filament(unsigned int filament_index) bool PresetBundle::is_the_only_edited_filament(unsigned int filament_index)
{ {

View File

@ -101,6 +101,8 @@ public:
void set_calibrate_printer(std::string name); void set_calibrate_printer(std::string name);
std::set<std::string> get_printer_names_by_printer_type_and_nozzle(const std::string &printer_type, const std::string &nozzle_diameter_str);
PresetCollection prints; PresetCollection prints;
PresetCollection sla_prints; PresetCollection sla_prints;
PresetCollection filaments; PresetCollection filaments;

View File

@ -792,8 +792,12 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
std::set<std::string> filament_id_set; std::set<std::string> filament_id_set;
PresetBundle * preset_bundle = wxGetApp().preset_bundle;
PresetBundle* preset_bundle = wxGetApp().preset_bundle; std::ostringstream stream;
stream << std::fixed << std::setprecision(1) << obj->nozzle_diameter;
std::string nozzle_diameter_str = stream.str();
std::set<std::string> printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(MachineObject::get_preset_printer_model_name(obj->printer_type), nozzle_diameter_str);
if (preset_bundle) { if (preset_bundle) {
BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size(); BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size();
for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) { for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) {
@ -805,79 +809,64 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
if (preset_bundle->filaments.get_preset_base(*filament_it) != &preset || (!filament_it->is_system && !obj->is_support_user_preset)) { if (preset_bundle->filaments.get_preset_base(*filament_it) != &preset || (!filament_it->is_system && !obj->is_support_user_preset)) {
continue; continue;
} }
ConfigOption * printer_opt = filament_it->config.option("compatible_printers");
ConfigOptionStrings *printer_strs = dynamic_cast<ConfigOptionStrings *>(printer_opt);
for (auto printer_str : printer_strs->values) {
if (printer_names.find(printer_str) != printer_names.end()) {
if (filament_id_set.find(filament_it->filament_id) != filament_id_set.end()) {
continue;
} else {
filament_id_set.insert(filament_it->filament_id);
// name matched
if (filament_it->is_system) {
filament_items.push_back(filament_it->alias);
FilamentInfos filament_infos;
filament_infos.filament_id = filament_it->filament_id;
filament_infos.setting_id = filament_it->setting_id;
map_filament_items[filament_it->alias] = filament_infos;
} else {
char target = '@';
size_t pos = filament_it->name.find(target);
if (pos != std::string::npos) {
std::string user_preset_alias = filament_it->name.substr(0, pos - 1);
wxString wx_user_preset_alias = wxString(user_preset_alias.c_str(), wxConvUTF8);
user_preset_alias = wx_user_preset_alias.ToStdString();
for (auto printer_it = preset_bundle->printers.begin(); printer_it != preset_bundle->printers.end(); printer_it++) { filament_items.push_back(user_preset_alias);
// filter by system preset
if (!printer_it->is_system) continue;
// get printer_model
ConfigOption* printer_model_opt = printer_it->config.option("printer_model");
ConfigOptionString* printer_model_str = dynamic_cast<ConfigOptionString*>(printer_model_opt);
if (!printer_model_str )
continue;
// use printer_model as printer type
if (printer_model_str->value != MachineObject::get_preset_printer_model_name(obj->printer_type))
continue;
ConfigOption* printer_opt = filament_it->config.option("compatible_printers");
ConfigOptionStrings* printer_strs = dynamic_cast<ConfigOptionStrings*>(printer_opt);
for (auto printer_str : printer_strs->values) {
if (printer_it->name == printer_str) {
if (filament_id_set.find(filament_it->filament_id) != filament_id_set.end()) {
continue;
}
else {
filament_id_set.insert(filament_it->filament_id);
// name matched
if (filament_it->is_system) {
filament_items.push_back(filament_it->alias);
FilamentInfos filament_infos; FilamentInfos filament_infos;
filament_infos.filament_id = filament_it->filament_id; filament_infos.filament_id = filament_it->filament_id;
filament_infos.setting_id = filament_it->setting_id; filament_infos.setting_id = filament_it->setting_id;
map_filament_items[filament_it->alias] = filament_infos; map_filament_items[user_preset_alias] = filament_infos;
} }
else {
char target = '@';
size_t pos = filament_it->name.find(target);
if (pos != std::string::npos) {
std::string user_preset_alias = filament_it->name.substr(0, pos-1);
wxString wx_user_preset_alias = wxString(user_preset_alias.c_str(), wxConvUTF8);
user_preset_alias = wx_user_preset_alias.ToStdString();
filament_items.push_back(user_preset_alias);
FilamentInfos filament_infos;
filament_infos.filament_id = filament_it->filament_id;
filament_infos.setting_id = filament_it->setting_id;
map_filament_items[user_preset_alias] = filament_infos;
}
}
if (filament_it->filament_id == ams_filament_id) {
selection_idx = idx;
// update if nozzle_temperature_range is found
ConfigOption* opt_min = filament_it->config.option("nozzle_temperature_range_low");
if (opt_min) {
ConfigOptionInts* opt_min_ints = dynamic_cast<ConfigOptionInts*>(opt_min);
if (opt_min_ints) {
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
}
}
ConfigOption* opt_max = filament_it->config.option("nozzle_temperature_range_high");
if (opt_max) {
ConfigOptionInts* opt_max_ints = dynamic_cast<ConfigOptionInts*>(opt_max);
if (opt_max_ints) {
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
}
}
}
idx++;
} }
if (filament_it->filament_id == ams_filament_id) {
selection_idx = idx;
// update if nozzle_temperature_range is found
ConfigOption *opt_min = filament_it->config.option("nozzle_temperature_range_low");
if (opt_min) {
ConfigOptionInts *opt_min_ints = dynamic_cast<ConfigOptionInts *>(opt_min);
if (opt_min_ints) {
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
}
}
ConfigOption *opt_max = filament_it->config.option("nozzle_temperature_range_high");
if (opt_max) {
ConfigOptionInts *opt_max_ints = dynamic_cast<ConfigOptionInts *>(opt_max);
if (opt_max_ints) {
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
}
}
}
idx++;
} }
} }
} }
} }
} }

View File

@ -1283,7 +1283,7 @@ void CreateFilamentPresetDialog::get_filament_presets_by_machine()
if (filament_types && filament_types->values.empty()) continue; if (filament_types && filament_types->values.empty()) continue;
const std::string filament_type = filament_types->values[0]; const std::string filament_type = filament_types->values[0];
if (filament_type != type_name) { if (filament_type != system_filament_types_map[type_name]) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " preset type is not selected type and preset name is: " << preset->name; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " preset type is not selected type and preset name is: " << preset->name;
continue; continue;
} }
@ -3217,6 +3217,7 @@ CreatePresetSuccessfulDialog::CreatePresetSuccessfulDialog(wxWindow *parent, con
wxBoxSizer *success_text_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *success_text_sizer = new wxBoxSizer(wxVERTICAL);
wxStaticText *success_text; wxStaticText *success_text;
wxStaticText *next_step_text; wxStaticText *next_step_text;
bool sync_user_preset_need_enabled = wxGetApp().getAgent() && wxGetApp().app_config->get("sync_user_preset") == "false";
switch (create_success_type) { switch (create_success_type) {
case PRINTER: case PRINTER:
success_text = new wxStaticText(this, wxID_ANY, _L("Printer Created")); success_text = new wxStaticText(this, wxID_ANY, _L("Printer Created"));
@ -3224,11 +3225,14 @@ CreatePresetSuccessfulDialog::CreatePresetSuccessfulDialog(wxWindow *parent, con
break; break;
case FILAMENT: case FILAMENT:
success_text = new wxStaticText(this, wxID_ANY, _L("Filament Created")); success_text = new wxStaticText(this, wxID_ANY, _L("Filament Created"));
next_step_text = new wxStaticText(this, wxID_ANY, _L("Please go to filament setting to edit your presets if you need.\nPlease note that nozzle temperature, hot bed temperature, and maximum volumetric speed has a significant impact on printing quality. Please set them carefully.")); wxString prompt_text = _L("Please go to filament setting to edit your presets if you need.\nPlease note that nozzle temperature, hot bed temperature, and maximum "
"volumetric speed has a significant impact on printing quality. Please set them carefully.");
wxString sync_text = sync_user_preset_need_enabled ? _L("\n\nStudio has detected that your user presets synchronization function is not enabled, which may result in unsuccessful Filament settings on "
"the Device page. \nClick \"Sync user presets\" to enable the synchronization function.") : "";
next_step_text = new wxStaticText(this, wxID_ANY, prompt_text + sync_text);
break; break;
} }
success_text->SetFont(Label::Head_18); success_text->SetFont(Label::Head_18);
//next_step_text->SetFont(Label::Body_14);
success_text_sizer->Add(success_text, 0, wxEXPAND, 0); success_text_sizer->Add(success_text, 0, wxEXPAND, 0);
success_text_sizer->Add(next_step_text, 0, wxEXPAND | wxTOP, FromDIP(5)); success_text_sizer->Add(next_step_text, 0, wxEXPAND | wxTOP, FromDIP(5));
horizontal_sizer->Add(success_text_sizer, 0, wxEXPAND | wxALL, FromDIP(5)); horizontal_sizer->Add(success_text_sizer, 0, wxEXPAND | wxALL, FromDIP(5));
@ -3242,8 +3246,7 @@ CreatePresetSuccessfulDialog::CreatePresetSuccessfulDialog(wxWindow *parent, con
case PRINTER: case PRINTER:
m_button_ok = new Button(this, _L("Printer Setting")); m_button_ok = new Button(this, _L("Printer Setting"));
break; break;
case FILAMENT: case FILAMENT: m_button_ok = sync_user_preset_need_enabled ? new Button(this, _L("Sync user presets")) : new Button(this, _L("OK"));
m_button_ok = new Button(this, _L("OK"));
break; break;
} }
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered), StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
@ -3260,9 +3263,15 @@ CreatePresetSuccessfulDialog::CreatePresetSuccessfulDialog(wxWindow *parent, con
m_button_ok->SetCornerRadius(FromDIP(12)); m_button_ok->SetCornerRadius(FromDIP(12));
btn_sizer->Add(m_button_ok, 0, wxRIGHT, FromDIP(10)); btn_sizer->Add(m_button_ok, 0, wxRIGHT, FromDIP(10));
m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { EndModal(wxID_OK); }); m_button_ok->Bind(wxEVT_LEFT_DOWN, [this, sync_user_preset_need_enabled](wxMouseEvent &e) {
if (sync_user_preset_need_enabled) {
wxGetApp().app_config->set("sync_user_preset", "true");
wxGetApp().start_sync_user_preset();
}
EndModal(wxID_OK);
});
if (PRINTER == create_success_type) { if (PRINTER == create_success_type || sync_user_preset_need_enabled) {
m_button_cancel = new Button(this, _L("Cancel")); m_button_cancel = new Button(this, _L("Cancel"));
m_button_cancel->SetBackgroundColor(btn_bg_white); m_button_cancel->SetBackgroundColor(btn_bg_white);
m_button_cancel->SetBorderColor(wxColour(38, 46, 48)); m_button_cancel->SetBorderColor(wxColour(38, 46, 48));

View File

@ -3424,7 +3424,6 @@ int MachineObject::parse_json(std::string payload)
; ;
} }
#pragma endregion #pragma endregion
try { try {
if (jj.contains("nozzle_diameter")) { if (jj.contains("nozzle_diameter")) {
if (jj["nozzle_diameter"].is_number_float()) { if (jj["nozzle_diameter"].is_number_float()) {
@ -3784,6 +3783,14 @@ int MachineObject::parse_json(std::string payload)
json j_ams = jj["ams"]["ams"]; json j_ams = jj["ams"]["ams"];
std::set<std::string> ams_id_set; std::set<std::string> ams_id_set;
PresetBundle *preset_bundle = Slic3r::GUI::wxGetApp().preset_bundle;
std::map<std::string, std::vector<Preset const *>> filament_list = preset_bundle->filaments.get_filament_presets();
std::ostringstream stream;
stream << std::fixed << std::setprecision(1) << nozzle_diameter;
std::string nozzle_diameter_str = stream.str();
std::set<std::string> printer_names = preset_bundle->get_printer_names_by_printer_type_and_nozzle(MachineObject::get_preset_printer_model_name(this->printer_type), nozzle_diameter_str);
for (auto it = amsList.begin(); it != amsList.end(); it++) { for (auto it = amsList.begin(); it != amsList.end(); it++) {
ams_id_set.insert(it->first); ams_id_set.insert(it->first);
} }
@ -3868,6 +3875,17 @@ int MachineObject::parse_json(std::string payload)
} else { } else {
curr_tray->type = type; curr_tray->type = type;
} }
if (filament_list.find(curr_tray->setting_id) == filament_list.end()) {
wxColour color = *wxWHITE;
char col_buf[10];
sprintf(col_buf, "%02X%02X%02XFF", (int) color.Red(), (int) color.Green(), (int) color.Blue());
try {
this->command_ams_filament_settings(std::stoi(ams_id), std::stoi(tray_id), "", "", std::string(col_buf), "", 0, 0);
continue;
} catch (...) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << " stoi error and ams_id: " << ams_id << " tray_id" << tray_id;
}
}
} else { } else {
curr_tray->setting_id = ""; curr_tray->setting_id = "";
curr_tray->type = ""; curr_tray->type = "";
@ -3900,14 +3918,62 @@ int MachineObject::parse_json(std::string payload)
curr_tray->bed_temp = (*tray_it)["bed_temp"].get<std::string>(); curr_tray->bed_temp = (*tray_it)["bed_temp"].get<std::string>();
else else
curr_tray->bed_temp = ""; curr_tray->bed_temp = "";
if (tray_it->contains("nozzle_temp_max")) if (tray_it->contains("tray_color")) {
auto color = (*tray_it)["tray_color"].get<std::string>();
curr_tray->update_color_from_str(color);
} else {
curr_tray->color = "";
}
if (tray_it->contains("nozzle_temp_max")) {
curr_tray->nozzle_temp_max = (*tray_it)["nozzle_temp_max"].get<std::string>(); curr_tray->nozzle_temp_max = (*tray_it)["nozzle_temp_max"].get<std::string>();
}
else else
curr_tray->nozzle_temp_max = ""; curr_tray->nozzle_temp_max = "";
if (tray_it->contains("nozzle_temp_min")) if (tray_it->contains("nozzle_temp_min"))
curr_tray->nozzle_temp_min = (*tray_it)["nozzle_temp_min"].get<std::string>(); curr_tray->nozzle_temp_min = (*tray_it)["nozzle_temp_min"].get<std::string>();
else else
curr_tray->nozzle_temp_min = ""; curr_tray->nozzle_temp_min = "";
if (curr_tray->nozzle_temp_min != "" && curr_tray->nozzle_temp_max != "") {
for (const Preset *preset : filament_list.find(curr_tray->setting_id)->second) {
ConfigOption *printer_opt = const_cast<Preset *>(preset)->config.option("compatible_printers");
ConfigOptionStrings *printer_strs = dynamic_cast<ConfigOptionStrings *>(printer_opt);
bool compared = false, is_correct = false;
for (const std::string &printer_str : printer_strs->values) {
if (printer_names.find(printer_str) != printer_names.end()) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << "nozzle temp matching: preset name: " << preset->name
<< " printer name: " << printer_str;
// Compare only once
if (!compared) {
compared = true;
bool min_temp_equation = false, max_temp_equation = false;
ConfigOption *opt_min = const_cast<Preset *>(preset)->config.option("nozzle_temperature_range_low");
if (opt_min) {
ConfigOptionInts *opt_min_ints = dynamic_cast<ConfigOptionInts *>(opt_min);
int min_nozzle_temp = opt_min_ints->get_at(0);
if (std::to_string(min_nozzle_temp) == curr_tray->nozzle_temp_min) min_temp_equation = true;
}
ConfigOption *opt_max = const_cast<Preset *>(preset)->config.option("nozzle_temperature_range_high");
if (opt_max) {
ConfigOptionInts *opt_max_ints = dynamic_cast<ConfigOptionInts *>(opt_max);
int max_nozzle_temp = opt_max_ints->get_at(0);
if (std::to_string(max_nozzle_temp) == curr_tray->nozzle_temp_max) max_temp_equation = true;
}
if (min_temp_equation && max_temp_equation) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << "Determine if the temperature has changed: no changed";
is_correct = true;
} else {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " " << __LINE__ << "Determine if the temperature has changed: has changed";
command_ams_filament_settings(std::stoi(ams_id), std::stoi(tray_id), preset->filament_id, preset->setting_id,
curr_tray->color, curr_tray->type, std::stoi(curr_tray->nozzle_temp_min),
std::stoi(curr_tray->nozzle_temp_max));
}
} else {
assert(false);
}
}
}
}
}
if (tray_it->contains("xcam_info")) if (tray_it->contains("xcam_info"))
curr_tray->xcam_info = (*tray_it)["xcam_info"].get<std::string>(); curr_tray->xcam_info = (*tray_it)["xcam_info"].get<std::string>();
else else
@ -3916,12 +3982,6 @@ int MachineObject::parse_json(std::string payload)
curr_tray->uuid = (*tray_it)["tray_uuid"].get<std::string>(); curr_tray->uuid = (*tray_it)["tray_uuid"].get<std::string>();
else else
curr_tray->uuid = "0"; curr_tray->uuid = "0";
if (tray_it->contains("tray_color")) {
auto color = (*tray_it)["tray_color"].get<std::string>();
curr_tray->update_color_from_str(color);
} else {
curr_tray->color = "";
}
if (tray_it->contains("ctype")) if (tray_it->contains("ctype"))
curr_tray->ctype = (*tray_it)["ctype"].get<int>(); curr_tray->ctype = (*tray_it)["ctype"].get<int>();