mirror of
https://github.com/QIDITECH/QIDIStudio.git
synced 2026-02-07 12:21:50 +03:00
fix some bug
This commit is contained in:
@@ -41,6 +41,9 @@ static std::string MachineBedTypeString[6] = {
|
||||
"suprtack"
|
||||
};
|
||||
|
||||
static wxString nozzle_not_set_text = _L("The printer nozzle information has not been set.\nPlease configure it before proceeding with the calibration.");
|
||||
static wxString nozzle_volume_type_not_match_text = _L("The nozzle type does not match the actual printer nozzle type.\nPlease click the Sync button above and restart the calibration.");
|
||||
|
||||
std::vector<std::string> not_support_auto_pa_cali_filaments = {
|
||||
"GFU03", // TPU 90A
|
||||
"GFU04" // TPU 85A
|
||||
@@ -84,6 +87,70 @@ wxString get_nozzle_volume_type_name(NozzleVolumeType type)
|
||||
return wxString();
|
||||
}
|
||||
|
||||
void update_speed_parameter( const std::string& key)
|
||||
{
|
||||
auto preset_bundle = wxGetApp().preset_bundle;
|
||||
auto& printer_config = preset_bundle->printers.get_edited_preset().config;
|
||||
auto& filament_config = preset_bundle->filaments.get_edited_preset().config;
|
||||
auto& print_config = preset_bundle->prints.get_edited_preset().config;
|
||||
|
||||
int extruder_nums = preset_bundle->get_printer_extruder_count();
|
||||
std::vector<int> extruder_types = printer_config.option<ConfigOptionEnumsGeneric>("extruder_type")->values;
|
||||
std::vector<int> nozzle_volume_types = preset_bundle->project_config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type")->values;
|
||||
|
||||
float nozzle_diameter = printer_config.option<ConfigOptionFloatsNullable>("nozzle_diameter")->values[0];
|
||||
float layer_height = print_config.option<ConfigOptionFloat>("layer_height")->value;
|
||||
float line_width = print_config.get_abs_value("line_width");
|
||||
|
||||
Flow flow = Flow(line_width, layer_height, nozzle_diameter);
|
||||
|
||||
for (size_t i = 0; i < extruder_nums; ++i) {
|
||||
int index = get_index_for_extruder_parameter(filament_config, "filament_max_volumetric_speed", i, ExtruderType(extruder_types[i]), NozzleVolumeType(nozzle_volume_types[i]));
|
||||
double filament_max_volumetric_speed = filament_config.option<ConfigOptionFloatsNullable>("filament_max_volumetric_speed")->get_at(index);
|
||||
double max_speed = filament_max_volumetric_speed / flow.mm3_per_mm();
|
||||
|
||||
index = get_index_for_extruder_parameter(print_config, key, i, ExtruderType(extruder_types[i]), NozzleVolumeType(nozzle_volume_types[i]));
|
||||
ConfigOptionFloatsNullable *speed_opt = print_config.option<ConfigOptionFloatsNullable>(key);
|
||||
speed_opt->values[index] = max_speed;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<double> generate_max_speed_parameter_value(const std::string &key)
|
||||
{
|
||||
auto preset_bundle = wxGetApp().preset_bundle;
|
||||
auto &printer_config = preset_bundle->printers.get_edited_preset().config;
|
||||
auto &filament_config = preset_bundle->filaments.get_edited_preset().config;
|
||||
auto &print_config = preset_bundle->prints.get_edited_preset().config;
|
||||
|
||||
int extruder_nums = preset_bundle->get_printer_extruder_count();
|
||||
std::vector<int> extruder_types = printer_config.option<ConfigOptionEnumsGeneric>("extruder_type")->values;
|
||||
std::vector<int> nozzle_volume_types = preset_bundle->project_config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type")->values;
|
||||
|
||||
float nozzle_diameter = printer_config.option<ConfigOptionFloatsNullable>("nozzle_diameter")->values[0];
|
||||
float layer_height = print_config.option<ConfigOptionFloat>("layer_height")->value;
|
||||
float line_width = print_config.get_abs_value("line_width");
|
||||
|
||||
Flow flow = Flow(line_width, layer_height, nozzle_diameter);
|
||||
|
||||
std::vector<double> speed_values;
|
||||
speed_values.resize(extruder_nums * nozzle_volume_types.size());
|
||||
|
||||
for (size_t i = 0; i < extruder_nums; ++i) {
|
||||
int index = get_index_for_extruder_parameter(filament_config, "filament_max_volumetric_speed", i, ExtruderType(extruder_types[i]),
|
||||
NozzleVolumeType(nozzle_volume_types[i]));
|
||||
double filament_max_volumetric_speed = filament_config.option<ConfigOptionFloatsNullable>("filament_max_volumetric_speed")->get_at(index);
|
||||
double max_speed = filament_max_volumetric_speed / flow.mm3_per_mm();
|
||||
|
||||
index = get_index_for_extruder_parameter(print_config, key, i, ExtruderType(extruder_types[i]), NozzleVolumeType(nozzle_volume_types[i]));
|
||||
ConfigOptionFloatsNullable *speed_opt = print_config.option<ConfigOptionFloatsNullable>(key);
|
||||
double speed_value = std::floor(std::min(speed_opt->values[index], max_speed));
|
||||
for (size_t v_id = 0; v_id < nozzle_volume_types.size(); ++v_id) {
|
||||
speed_values.emplace_back(speed_value);
|
||||
}
|
||||
}
|
||||
return speed_values;
|
||||
}
|
||||
|
||||
static int get_physical_extruder_idx(std::vector<int> physical_extruder_maps, int extruder_id)
|
||||
{
|
||||
for (size_t index = 0; index < physical_extruder_maps.size(); ++index) {
|
||||
@@ -164,6 +231,8 @@ static wxString to_wstring_name(std::string name)
|
||||
return _L("Stainless Steel");
|
||||
} else if (name == "tungsten_carbide") {
|
||||
return _L("Tungsten Carbide");
|
||||
} else if (name == "brass") {
|
||||
return _L("Brass");
|
||||
}
|
||||
|
||||
return wxEmptyString;
|
||||
@@ -294,6 +363,7 @@ static void init_multi_extruder_params_for_cali(DynamicPrintConfig& config, cons
|
||||
{
|
||||
nozzle_volume_types[index] = (int) calib_info.nozzle_volume_type;
|
||||
extruder_id = index + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -870,6 +940,7 @@ void CalibUtils::set_for_auto_pa_model_and_config(const std::vector<CalibInfo> &
|
||||
_wall_generator->value = PerimeterGeneratorType::Arachne;
|
||||
|
||||
print_config.option<ConfigOptionBool>("enable_prime_tower")->value = false;
|
||||
print_config.option<ConfigOptionBool>("enable_wrapping_detection")->value = false;
|
||||
|
||||
auto get_new_filament_id = [&sorted_calib_infos](int index) -> int {
|
||||
for (size_t i = 0; i < sorted_calib_infos.size(); ++i) {
|
||||
@@ -913,6 +984,7 @@ void CalibUtils::set_for_auto_pa_model_and_config(const std::vector<CalibInfo> &
|
||||
for (size_t index = 0; index < extruder_count; ++index) {
|
||||
if (physical_extruder_maps[index] == extruder_id) {
|
||||
extruder_id = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
nozzle_volume_types[extruder_id] = (int)calib_info.nozzle_volume_type;
|
||||
@@ -988,17 +1060,24 @@ bool CalibUtils::calib_generic_auto_pa_cali(const std::vector<CalibInfo> &calib_
|
||||
|
||||
Preset printer_preset = *calib_infos[0].printer_prest;
|
||||
Preset print_preset = *calib_infos[0].print_prest;
|
||||
|
||||
std::vector<CalibInfo> sorted_calib_infos = calib_infos;
|
||||
std::sort(sorted_calib_infos.begin(), sorted_calib_infos.end(), [](const CalibInfo &left_item, const CalibInfo &right_item) {
|
||||
return left_item.index < right_item.index;
|
||||
});
|
||||
|
||||
std::vector<Preset> filament_presets;
|
||||
std::vector<int> filament_map;
|
||||
filament_map.resize(calib_infos.size());
|
||||
filament_map.resize(sorted_calib_infos.size());
|
||||
std::vector<int> physical_extruder_maps = dynamic_cast<ConfigOptionInts *>(printer_config.option("physical_extruder_map", true))->values;
|
||||
for (size_t i = 0; i < calib_infos.size(); ++i) {
|
||||
CalibInfo calib_info = calib_infos[i];
|
||||
for (size_t i = 0; i < sorted_calib_infos.size(); ++i) {
|
||||
CalibInfo calib_info = sorted_calib_infos[i];
|
||||
calib_info.filament_prest->config.set_key_value("curr_bed_type", new ConfigOptionEnum<BedType>(calib_info.bed_type));
|
||||
filament_presets.emplace_back(*calib_info.filament_prest);
|
||||
for (size_t index = 0; index < physical_extruder_maps.size(); ++index) {
|
||||
if (physical_extruder_maps[index] == calib_info.extruder_id) {
|
||||
filament_map[i] = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1006,7 +1085,7 @@ bool CalibUtils::calib_generic_auto_pa_cali(const std::vector<CalibInfo> &calib_
|
||||
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
||||
DynamicPrintConfig full_config = PresetBundle::construct_full_config(printer_preset, print_preset, preset_bundle->project_config, filament_presets, false, filament_map);
|
||||
|
||||
set_for_auto_pa_model_and_config(calib_infos, full_config, model);
|
||||
set_for_auto_pa_model_and_config(sorted_calib_infos, full_config, model);
|
||||
if (!process_and_store_3mf(&model, full_config, params, error_message))
|
||||
return false;
|
||||
|
||||
@@ -1036,7 +1115,7 @@ bool CalibUtils::calib_generic_auto_pa_cali(const std::vector<CalibInfo> &calib_
|
||||
agent->track_event("cali", js.dump());
|
||||
} catch (...) {}
|
||||
|
||||
send_to_print(calib_infos, error_message);
|
||||
send_to_print(sorted_calib_infos, error_message);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1430,20 +1509,12 @@ bool CalibUtils::check_printable_status_before_cali(const MachineObject *obj, co
|
||||
}
|
||||
|
||||
bool is_multi_extruder = obj->is_multi_extruders();
|
||||
std::vector<NozzleFlowType> nozzle_volume_types;
|
||||
if (is_multi_extruder) {
|
||||
for (const DevExtder& extruder : obj->GetExtderSystem()->GetExtruders()) {
|
||||
nozzle_volume_types.emplace_back(extruder.GetNozzleFlowType());
|
||||
}
|
||||
}
|
||||
|
||||
Preset *printer_preset = get_printer_preset(obj);
|
||||
|
||||
for (const auto &cali_info : cali_infos.calib_datas) {
|
||||
wxString name = _L("left");
|
||||
if (cali_info.extruder_id == 0) {
|
||||
name = _L("right");
|
||||
}
|
||||
wxString name = "";
|
||||
if (is_multi_extruder) { name = cali_info.extruder_id == MAIN_EXTRUDER_ID ? _L("right") + " ": _L("left") + " "; }
|
||||
|
||||
float cali_diameter = cali_info.nozzle_diameter;
|
||||
int extruder_id = cali_info.extruder_id;
|
||||
@@ -1452,7 +1523,14 @@ bool CalibUtils::check_printable_status_before_cali(const MachineObject *obj, co
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (is_approx(double(cali_info.nozzle_diameter), 0.2) && !obj->is_series_x()) {
|
||||
error_message = wxString::Format(_L("The nozzle diameter of %sextruder is 0.2mm which does not support automatic Flow Dynamics calibration."), name);
|
||||
return false;
|
||||
}
|
||||
|
||||
float diameter = obj->GetExtderSystem()->GetNozzleDiameter(extruder_id);
|
||||
NozzleFlowType nozzle_volume_type = obj->GetExtderSystem()->GetNozzleFlowType(extruder_id);
|
||||
if (!is_approx(cali_info.nozzle_diameter, diameter)) {
|
||||
if (is_multi_extruder)
|
||||
error_message = wxString::Format(_L("The currently selected nozzle diameter of %s extruder does not match the actual nozzle diameter.\n"
|
||||
@@ -1463,18 +1541,21 @@ bool CalibUtils::check_printable_status_before_cali(const MachineObject *obj, co
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_multi_extruder) {
|
||||
if (nozzle_volume_types[cali_info.extruder_id] == NozzleFlowType::NONE_FLOWTYPE) {
|
||||
|
||||
if (nozzle_volume_type == NozzleFlowType::NONE_FLOWTYPE) {
|
||||
if (is_multi_extruder)
|
||||
error_message = wxString::Format(_L("Printer %s nozzle information has not been set. Please configure it before proceeding with the calibration."), name);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
error_message = nozzle_not_set_text;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NozzleVolumeType(nozzle_volume_types[cali_info.extruder_id] - 1) != cali_info.nozzle_volume_type) {
|
||||
if (NozzleVolumeType(nozzle_volume_type - 1) != cali_info.nozzle_volume_type) {
|
||||
if (is_multi_extruder)
|
||||
error_message = wxString::Format(_L("The currently selected nozzle type of %s extruder does not match the actual printer nozzle type.\n"
|
||||
"Please click the Sync button above and restart the calibration."), name);
|
||||
return false;
|
||||
}
|
||||
"Please click the Sync button above and restart the calibration."), name);
|
||||
else
|
||||
error_message = nozzle_volume_type_not_match_text;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -1490,61 +1571,62 @@ bool CalibUtils::check_printable_status_before_cali(const MachineObject *obj, co
|
||||
if (cali_infos.empty())
|
||||
return true;
|
||||
|
||||
float cali_diameter = cali_infos[0].nozzle_diameter;
|
||||
int extruder_id = cali_infos[0].extruder_id;
|
||||
bool is_multi_extruder = obj->is_multi_extruders();
|
||||
Preset *printer_preset = get_printer_preset(obj);
|
||||
|
||||
for (const auto &cali_info : cali_infos) {
|
||||
if (cali_infos[0].params.mode == CalibMode::Calib_Auto_PA_Line && !is_support_auto_pa_cali(cali_info.filament_prest->filament_id)) {
|
||||
wxString name = "";
|
||||
if (is_multi_extruder) { name = cali_info.extruder_id == MAIN_EXTRUDER_ID ? _L("right") + " " : _L("left") + " "; }
|
||||
|
||||
if (cali_info.params.mode == CalibMode::Calib_Auto_PA_Line && !is_support_auto_pa_cali(cali_info.filament_prest->filament_id)) {
|
||||
error_message = _L("TPU 90A/TPU 85A is too soft and does not support automatic Flow Dynamics calibration.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_approx(cali_diameter, cali_info.nozzle_diameter)) {
|
||||
error_message = _L("Automatic calibration only supports cases where the left and right nozzle diameters are identical.");
|
||||
|
||||
if (is_approx(double(cali_info.nozzle_diameter), 0.2) && !obj->is_series_x()) {
|
||||
error_message = wxString::Format(_L("The nozzle diameter of %sextruder is 0.2mm which does not support automatic Flow Dynamics calibration."), name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (extruder_id >= obj->GetExtderSystem()->GetExtruders().size()) {
|
||||
error_message = _L("The number of printer extruders and the printer selected for calibration does not match.");
|
||||
return false;
|
||||
}
|
||||
float cali_diameter = cali_info.nozzle_diameter;
|
||||
int extruder_id = cali_info.extruder_id;
|
||||
if (extruder_id >= obj->GetExtderSystem()->GetTotalExtderSize()) {
|
||||
error_message = _L("The number of printer extruders and the printer selected for calibration does not match.");
|
||||
return false;
|
||||
}
|
||||
|
||||
float diameter = obj->GetExtderSystem()->GetNozzleDiameter(extruder_id);
|
||||
bool is_multi_extruder = obj->is_multi_extruders();
|
||||
std::vector<NozzleFlowType> nozzle_volume_types;
|
||||
if (is_multi_extruder) {
|
||||
for (auto &extruder : obj->GetExtderSystem()->GetExtruders()) { nozzle_volume_types.emplace_back(extruder.GetNozzleFlowType()); }
|
||||
}
|
||||
|
||||
for (const auto &cali_info : cali_infos) {
|
||||
wxString name = _L("left");
|
||||
if (cali_info.extruder_id == 0) { name = _L("right"); }
|
||||
float diameter = obj->GetExtderSystem()->GetNozzleDiameter(extruder_id);
|
||||
NozzleFlowType nozzle_volume_type = obj->GetExtderSystem()->GetNozzleFlowType(cali_info.extruder_id);
|
||||
|
||||
if (!is_approx(cali_info.nozzle_diameter, diameter)) {
|
||||
if (is_multi_extruder)
|
||||
error_message = wxString::Format(_L("The currently selected nozzle diameter of %s extruder does not match the actual nozzle diameter.\n"
|
||||
"Please click the Sync button above and restart the calibration."),
|
||||
name);
|
||||
"Please click the Sync button above and restart the calibration."), name);
|
||||
else
|
||||
error_message = _L("The nozzle diameter does not match the actual printer nozzle diameter.\n"
|
||||
"Please click the Sync button above and restart the calibration.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_multi_extruder) {
|
||||
if (nozzle_volume_types[cali_info.extruder_id] == NozzleFlowType::NONE_FLOWTYPE) {
|
||||
if (nozzle_volume_type == NozzleFlowType::NONE_FLOWTYPE) {
|
||||
if (is_multi_extruder)
|
||||
error_message = wxString::Format(_L("Printer %s nozzle information has not been set. Please configure it before proceeding with the calibration."), name);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
error_message = nozzle_not_set_text;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NozzleVolumeType(nozzle_volume_types[cali_info.extruder_id] - 1) != cali_info.nozzle_volume_type) {
|
||||
if (NozzleVolumeType(nozzle_volume_type - 1) != cali_info.nozzle_volume_type) {
|
||||
if (is_multi_extruder)
|
||||
error_message = wxString::Format(_L("The currently selected nozzle type of %s extruder does not match the actual printer nozzle type.\n"
|
||||
"Please click the Sync button above and restart the calibration."),
|
||||
name);
|
||||
return false;
|
||||
}
|
||||
"Please click the Sync button above and restart the calibration."), name);
|
||||
else
|
||||
error_message = nozzle_volume_type_not_match_text;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1558,20 +1640,16 @@ bool CalibUtils::check_printable_status_before_cali(const MachineObject* obj, co
|
||||
const ConfigOptionFloatsNullable *nozzle_diameter_config = cali_info.printer_prest->config.option<ConfigOptionFloatsNullable>("nozzle_diameter");
|
||||
float nozzle_diameter = nozzle_diameter_config->values[0];
|
||||
|
||||
float diameter = obj->GetExtderSystem()->GetNozzleDiameter(cali_info.extruder_id);
|
||||
bool is_multi_extruder = obj->is_multi_extruders();
|
||||
std::vector<NozzleFlowType> nozzle_volume_types;
|
||||
if (is_multi_extruder) {
|
||||
for (const DevExtder& extruder : obj->GetExtderSystem()->GetExtruders()) {
|
||||
nozzle_volume_types.emplace_back(extruder.GetNozzleFlowType());
|
||||
}
|
||||
}
|
||||
|
||||
wxString name = _L("left");
|
||||
if (cali_info.extruder_id == 0) {
|
||||
name = _L("right");
|
||||
}
|
||||
|
||||
float diameter = obj->GetExtderSystem()->GetNozzleDiameter(cali_info.extruder_id);
|
||||
NozzleFlowType nozzle_volume_type = obj->GetExtderSystem()->GetNozzleFlowType(cali_info.extruder_id);
|
||||
|
||||
if (!is_approx(nozzle_diameter, diameter)) {
|
||||
if (is_multi_extruder)
|
||||
error_message = wxString::Format(_L("The currently selected nozzle diameter of %s extruder does not match the actual nozzle diameter.\n"
|
||||
@@ -1582,17 +1660,22 @@ bool CalibUtils::check_printable_status_before_cali(const MachineObject* obj, co
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_multi_extruder) {
|
||||
if (nozzle_volume_types[cali_info.extruder_id] == NozzleFlowType::NONE_FLOWTYPE) {
|
||||
error_message = wxString::Format(_L("Printer %s nozzle information has not been set. Please configure it before proceeding with the calibration."), name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NozzleVolumeType(nozzle_volume_types[cali_info.extruder_id] - 1) != cali_info.nozzle_volume_type) {
|
||||
if (nozzle_volume_type == NozzleFlowType::NONE_FLOWTYPE) {
|
||||
if (is_multi_extruder)
|
||||
error_message = wxString::Format(_L("Printer %s nozzle information has not been set. Please configure it before proceeding with the calibration."), name);
|
||||
else
|
||||
error_message = nozzle_not_set_text;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NozzleVolumeType(nozzle_volume_type - 1) != cali_info.nozzle_volume_type) {
|
||||
if (is_multi_extruder)
|
||||
error_message = wxString::Format(_L("The currently selected nozzle type of %s extruder does not match the actual printer nozzle type.\n"
|
||||
"Please click the Sync button above and restart the calibration."), name);
|
||||
return false;
|
||||
}
|
||||
"Please click the Sync button above and restart the calibration."), name);
|
||||
else
|
||||
error_message = nozzle_volume_type_not_match_text;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1871,6 +1954,7 @@ void CalibUtils::send_to_print(const CalibInfo &calib_info, wxString &error_mess
|
||||
print_job->set_calibration_task(true);
|
||||
|
||||
print_job->has_sdcard = obj_->GetStorage()->get_sdcard_state() == DevStorage::HAS_SDCARD_NORMAL;
|
||||
print_job->could_emmc_print = obj_->is_support_print_with_emmc;
|
||||
print_job->set_print_config(MachineBedTypeString[bed_type], true, false, false, false, true, false, 0, 0, 0, 0);
|
||||
print_job->set_print_job_finished_event(wxGetApp().plater()->get_send_calibration_finished_event(), print_job->m_project_name);
|
||||
|
||||
@@ -1987,6 +2071,7 @@ void CalibUtils::send_to_print(const std::vector<CalibInfo> &calib_infos, wxStri
|
||||
print_job->set_calibration_task(true);
|
||||
|
||||
print_job->has_sdcard = obj_->GetStorage()->get_sdcard_state() == DevStorage::HAS_SDCARD_NORMAL;
|
||||
print_job->could_emmc_print = obj_->is_support_print_with_emmc;
|
||||
print_job->set_print_config(MachineBedTypeString[bed_type], true, true, false, false, true, false, 0, 1, 0, 0);
|
||||
print_job->set_print_job_finished_event(wxGetApp().plater()->get_send_calibration_finished_event(), print_job->m_project_name);
|
||||
|
||||
|
||||
@@ -98,6 +98,8 @@ extern void get_default_k_n_value(const std::string &filament_id, float &k, floa
|
||||
extern wxString get_nozzle_volume_type_name(NozzleVolumeType type);
|
||||
extern bool is_pa_params_valid(const Calib_Params ¶ms);
|
||||
|
||||
extern void update_speed_parameter(const std::string &key);
|
||||
extern std::vector<double> generate_max_speed_parameter_value(const std::string &key);
|
||||
|
||||
}
|
||||
}
|
||||
301
src/slic3r/Utils/CertificateVerify.cpp
Normal file
301
src/slic3r/Utils/CertificateVerify.cpp
Normal file
@@ -0,0 +1,301 @@
|
||||
#include "CertificateVerify.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#define _WIN32_WINNT 0x0601
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
static std::wstring utf8_to_w(const std::string& s) {
|
||||
if (s.empty()) return L"";
|
||||
int n = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), (int)s.size(), nullptr, 0);
|
||||
std::wstring w(n, L'\0');
|
||||
MultiByteToWideChar(CP_UTF8, 0, s.c_str(), (int)s.size(), w.data(), n);
|
||||
return w;
|
||||
}
|
||||
|
||||
static std::wstring wself_path() {
|
||||
wchar_t buf[MAX_PATH];
|
||||
DWORD n = GetModuleFileNameW(nullptr, buf, MAX_PATH);
|
||||
return std::wstring(buf, buf + n);
|
||||
}
|
||||
|
||||
static bool sha256_win(const BYTE* data, DWORD len, std::array<uint8_t, 32>& out) {
|
||||
HCRYPTPROV hProv = 0;
|
||||
HCRYPTHASH hHash = 0;
|
||||
if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
|
||||
return false;
|
||||
bool ok = false;
|
||||
if (CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) {
|
||||
if (CryptHashData(hHash, data, len, 0)) {
|
||||
DWORD cb = (DWORD)out.size();
|
||||
ok = (CryptGetHashParam(hHash, HP_HASHVAL, out.data(), &cb, 0) && cb == out.size());
|
||||
}
|
||||
CryptDestroyHash(hHash);
|
||||
}
|
||||
CryptReleaseContext(hProv, 0);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static std::string wide_to_utf8(const std::wstring& w) {
|
||||
if (w.empty()) return {};
|
||||
int n = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), (int)w.size(), nullptr, 0, nullptr, nullptr);
|
||||
std::string s(n, '\0');
|
||||
WideCharToMultiByte(CP_UTF8, 0, w.c_str(), (int)w.size(), s.data(), n, nullptr, nullptr);
|
||||
return s;
|
||||
}
|
||||
|
||||
static std::optional<SignerSummary> summarize_file_win(const std::wstring& path) {
|
||||
HCERTSTORE hStore = nullptr;
|
||||
HCRYPTMSG hMsg = nullptr;
|
||||
|
||||
if (!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
|
||||
path.c_str(),
|
||||
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
|
||||
CERT_QUERY_FORMAT_FLAG_BINARY,
|
||||
0, nullptr, nullptr, nullptr,
|
||||
&hStore, &hMsg, nullptr)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
DWORD cb = 0;
|
||||
if (!CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, nullptr, &cb) || cb == 0) {
|
||||
CryptMsgClose(hMsg); CertCloseStore(hStore, 0);
|
||||
return std::nullopt;
|
||||
}
|
||||
std::vector<BYTE> v(cb);
|
||||
if (!CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, v.data(), &cb)) {
|
||||
CryptMsgClose(hMsg); CertCloseStore(hStore, 0);
|
||||
return std::nullopt;
|
||||
}
|
||||
auto* si = reinterpret_cast<PCMSG_SIGNER_INFO>(v.data());
|
||||
|
||||
CERT_INFO ci{};
|
||||
ci.Issuer = si->Issuer;
|
||||
ci.SerialNumber = si->SerialNumber;
|
||||
|
||||
PCCERT_CONTEXT pCert = CertFindCertificateInStore(
|
||||
hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
|
||||
CERT_FIND_SUBJECT_CERT, &ci, nullptr);
|
||||
|
||||
if (!pCert) {
|
||||
CryptMsgClose(hMsg); CertCloseStore(hStore, 0);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
SignerSummary s{};
|
||||
|
||||
// 1) cert_sha256
|
||||
DWORD cbHash = (DWORD)s.cert_sha256.size();
|
||||
if (!CertGetCertificateContextProperty(
|
||||
pCert, CERT_SHA256_HASH_PROP_ID,
|
||||
s.cert_sha256.data(), &cbHash) || cbHash != s.cert_sha256.size()) {
|
||||
sha256_win(pCert->pbCertEncoded, pCert->cbCertEncoded, s.cert_sha256);
|
||||
}
|
||||
|
||||
// 2) spki_sha256 SPKI -> DER -> hash
|
||||
DWORD cbSpki = 0;
|
||||
if (!CryptEncodeObjectEx(
|
||||
X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
|
||||
&pCert->pCertInfo->SubjectPublicKeyInfo,
|
||||
0, nullptr, nullptr, &cbSpki)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<BYTE> spki(cbSpki);
|
||||
if (!CryptEncodeObjectEx(
|
||||
X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
|
||||
&pCert->pCertInfo->SubjectPublicKeyInfo,
|
||||
0, nullptr, spki.data(), &cbSpki)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
sha256_win(spki.data(), cbSpki, s.spki_sha256);
|
||||
|
||||
// 3) subject/issuer
|
||||
{
|
||||
wchar_t buf[1024];
|
||||
DWORD n1 = CertGetNameStringW(pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr, buf, 1024);
|
||||
if (n1 > 0) s.subject_dn = wide_to_utf8(std::wstring(buf, buf + (n1 ? n1 - 1 : 0)));
|
||||
DWORD n2 = CertGetNameStringW(pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG,
|
||||
nullptr, buf, 1024);
|
||||
if (n2 > 0) s.issuer_dn = wide_to_utf8(std::wstring(buf, buf + (n2 ? n2 - 1 : 0)));
|
||||
}
|
||||
|
||||
CertFreeCertificateContext(pCert);
|
||||
CryptMsgClose(hMsg);
|
||||
CertCloseStore(hStore, 0);
|
||||
return s;
|
||||
}
|
||||
|
||||
std::optional<SignerSummary> SummarizeSelf() {
|
||||
try {
|
||||
return summarize_file_win(wself_path());
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << e.what();
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<SignerSummary> SummarizeModule(const std::string& path_utf8) {
|
||||
try {
|
||||
return summarize_file_win(utf8_to_w(path_utf8));
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << e.what();
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
#include <cstring>
|
||||
#include <TargetConditionals.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
#include <CommonCrypto/CommonCrypto.h>
|
||||
|
||||
static bool sha256_mac(const void* data, size_t len, std::array<uint8_t, 32>& out) {
|
||||
CC_SHA256_CTX ctx; CC_SHA256_Init(&ctx);
|
||||
CC_SHA256_Update(&ctx, data, (CC_LONG)len);
|
||||
CC_SHA256_Final(out.data(), &ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string cfstr(CFStringRef s) {
|
||||
if (!s) return {};
|
||||
CFIndex len = CFStringGetLength(s);
|
||||
CFIndex max = CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8);
|
||||
std::string out(static_cast<size_t>(max) + 1, '\0');
|
||||
if (CFStringGetCString(s, out.data(), max, kCFStringEncodingUTF8)) {
|
||||
out.resize(strlen(out.c_str()));
|
||||
return out;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static std::string dn_from_cert(SecCertificateRef cert) {
|
||||
CFStringRef s = SecCertificateCopySubjectSummary(cert);
|
||||
std::string out = cfstr(s);
|
||||
if (s) CFRelease(s);
|
||||
return out;
|
||||
}
|
||||
|
||||
static bool fill_from_static_code(SecStaticCodeRef code, SignerSummary& s) {
|
||||
CFDictionaryRef info = nullptr;
|
||||
auto copy_inf_ret = SecCodeCopySigningInformation(code, kSecCSSigningInformation | kSecCSRequirementInformation | kSecCSInternalInformation, &info);
|
||||
if (copy_inf_ret != errSecSuccess) {
|
||||
return false;
|
||||
}
|
||||
if (!info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auto tid = (CFStringRef)CFDictionaryGetValue(info, kSecCodeInfoTeamIdentifier)) {
|
||||
s.team_id = cfstr(tid);
|
||||
}
|
||||
|
||||
// cert chain
|
||||
CFArrayRef certs = (CFArrayRef)CFDictionaryGetValue(info, kSecCodeInfoCertificates);
|
||||
if (!certs || CFArrayGetCount(certs) == 0) {
|
||||
CFRelease(info);
|
||||
return false;
|
||||
}
|
||||
SecCertificateRef leaf = (SecCertificateRef)CFArrayGetValueAtIndex(certs, 0);
|
||||
|
||||
// 1) cert_sha256
|
||||
if (auto der = SecCertificateCopyData(leaf)) {
|
||||
sha256_mac(CFDataGetBytePtr(der), CFDataGetLength(der), s.cert_sha256);
|
||||
CFRelease(der);
|
||||
}
|
||||
|
||||
// 2) spki_sha256
|
||||
if (auto pk = SecCertificateCopyKey(leaf)) {
|
||||
CFDataRef raw = SecKeyCopyExternalRepresentation(pk, nullptr);
|
||||
if (raw) {
|
||||
sha256_mac(CFDataGetBytePtr(raw), CFDataGetLength(raw), s.spki_sha256);
|
||||
CFRelease(raw);
|
||||
}
|
||||
CFRelease(pk);
|
||||
}
|
||||
|
||||
// 3) subject / issuer
|
||||
s.subject_dn = dn_from_cert(leaf);
|
||||
if (CFArrayGetCount(certs) >= 2) {
|
||||
SecCertificateRef iss = (SecCertificateRef)CFArrayGetValueAtIndex(certs, 1);
|
||||
s.issuer_dn = dn_from_cert(iss);
|
||||
}
|
||||
|
||||
CFRelease(info);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<SignerSummary> SummarizeSelf() {
|
||||
try {
|
||||
SecCodeRef dyn = nullptr;
|
||||
auto copy_ret = SecCodeCopySelf(kSecCSDefaultFlags, &dyn);
|
||||
if (copy_ret != errSecSuccess) {
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!dyn) {
|
||||
return std::nullopt;
|
||||
}
|
||||
SecStaticCodeRef st = nullptr;
|
||||
auto copy_static_ret = SecCodeCopyStaticCode(dyn, kSecCSDefaultFlags, &st);
|
||||
CFRelease(dyn);
|
||||
if (!st) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
SignerSummary s{};
|
||||
bool ok = fill_from_static_code(st, s);
|
||||
CFRelease(st);
|
||||
return ok ? std::optional<SignerSummary>(s) : std::nullopt;
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << e.what();
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<SignerSummary> SummarizeModule(const std::string& path_utf8) {
|
||||
try {
|
||||
CFURLRef url = CFURLCreateFromFileSystemRepresentation(nullptr, (const UInt8 *) path_utf8.c_str(), path_utf8.size(), false);
|
||||
if (!url) return std::nullopt;
|
||||
|
||||
SecStaticCodeRef code = nullptr;
|
||||
OSStatus st = SecStaticCodeCreateWithPath(url, kSecCSDefaultFlags, &code);
|
||||
CFRelease(url);
|
||||
if (st != errSecSuccess || !code) return std::nullopt;
|
||||
|
||||
SignerSummary s{};
|
||||
bool ok = fill_from_static_code(code, s);
|
||||
CFRelease(code);
|
||||
return ok ? std::optional<SignerSummary>(s) : std::nullopt;
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << e.what();
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
std::optional<SignerSummary> SummarizeSelf() { return std::nullopt; }
|
||||
std::optional<SignerSummary> SummarizeModule(const std::string&) { return std::nullopt; }
|
||||
#endif
|
||||
|
||||
bool IsSamePublisher(const SignerSummary& a, const SignerSummary& b)
|
||||
{
|
||||
if (!a.team_id.empty() && a.team_id == b.team_id) return true;
|
||||
if (a.spki_sha256 == b.spki_sha256) return true;
|
||||
if (a.cert_sha256 == b.cert_sha256) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
35
src/slic3r/Utils/CertificateVerify.hpp
Normal file
35
src/slic3r/Utils/CertificateVerify.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
namespace Slic3r {
|
||||
struct SignerSummary {
|
||||
// generic
|
||||
std::array<uint8_t, 32> cert_sha256;
|
||||
std::array<uint8_t, 32> spki_sha256;
|
||||
std::string subject_dn;
|
||||
std::string issuer_dn;
|
||||
|
||||
// macOS only
|
||||
std::string team_id;
|
||||
|
||||
SignerSummary() {
|
||||
cert_sha256.fill(0);
|
||||
spki_sha256.fill(0);
|
||||
}
|
||||
|
||||
std::string as_print() const {
|
||||
std::stringstream ss;
|
||||
ss << " subject_dn: " << subject_dn << " issuer_dn: " << issuer_dn << " team_id: " << team_id;
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
bool IsSamePublisher(const SignerSummary& a, const SignerSummary& b);
|
||||
|
||||
std::optional<SignerSummary> SummarizeSelf();
|
||||
|
||||
std::optional<SignerSummary> SummarizeModule(const std::string& path_utf8);
|
||||
}
|
||||
219
src/slic3r/Utils/FileTransferUtils.cpp
Normal file
219
src/slic3r/Utils/FileTransferUtils.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
#include <wx/wx.h>
|
||||
#include <type_traits>
|
||||
#include "FileTransferUtils.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/DeviceCore/DevManager.h"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
FileTransferModule::FileTransferModule(ModuleHandle networking_module, int required_abi_version) : networking_(networking_module)
|
||||
{
|
||||
// basic
|
||||
ft_abi_version = sym_lookup<fn_ft_abi_version>(networking_, "ft_abi_version");
|
||||
ft_free = sym_lookup<fn_ft_free>(networking_, "ft_free");
|
||||
ft_job_result_destroy = sym_lookup<fn_ft_job_result_destroy>(networking_, "ft_job_result_destroy");
|
||||
ft_job_msg_destroy = sym_lookup<fn_ft_job_msg_destroy>(networking_, "ft_job_msg_destroy");
|
||||
|
||||
// tunnel
|
||||
ft_tunnel_create = sym_lookup<fn_ft_tunnel_create>(networking_, "ft_tunnel_create");
|
||||
ft_tunnel_retain = sym_lookup<fn_ft_tunnel_retain>(networking_, "ft_tunnel_retain");
|
||||
ft_tunnel_release = sym_lookup<fn_ft_tunnel_release>(networking_, "ft_tunnel_release");
|
||||
ft_tunnel_start_connect = sym_lookup<fn_ft_tunnel_start_connect>(networking_, "ft_tunnel_start_connect");
|
||||
ft_tunnel_sync_connect = sym_lookup<fn_ft_tunnel_sync_connect>(networking_, "ft_tunnel_sync_connect");
|
||||
ft_tunnel_set_status_cb = sym_lookup<fn_ft_tunnel_set_status_cb>(networking_, "ft_tunnel_set_status_cb");
|
||||
ft_tunnel_shutdown = sym_lookup<fn_ft_tunnel_shutdown>(networking_, "ft_tunnel_shutdown");
|
||||
|
||||
// job
|
||||
ft_job_create = sym_lookup<fn_ft_job_create>(networking_, "ft_job_create");
|
||||
ft_job_retain = sym_lookup<fn_ft_job_retain>(networking_, "ft_job_retain");
|
||||
ft_job_release = sym_lookup<fn_ft_job_release>(networking_, "ft_job_release");
|
||||
ft_job_set_result_cb = sym_lookup<fn_ft_job_set_result_cb>(networking_, "ft_job_set_result_cb");
|
||||
ft_job_get_result = sym_lookup<fn_ft_job_get_result>(networking_, "ft_job_get_result");
|
||||
ft_tunnel_start_job = sym_lookup<fn_ft_tunnel_start_job>(networking_, "ft_tunnel_start_job");
|
||||
ft_job_cancel = sym_lookup<fn_ft_job_cancel>(networking_, "ft_job_cancel");
|
||||
|
||||
ft_job_set_msg_cb = sym_lookup<fn_ft_job_set_msg_cb>(networking_, "ft_job_set_msg_cb");
|
||||
ft_job_try_get_msg = sym_lookup<fn_ft_job_try_get_msg>(networking_, "ft_job_try_get_msg");
|
||||
ft_job_get_msg = sym_lookup<fn_ft_job_get_msg>(networking_, "ft_job_get_msg");
|
||||
}
|
||||
|
||||
FileTransferTunnel::FileTransferTunnel(FileTransferModule &m, const std::string &url) : m_(&m)
|
||||
{
|
||||
FT_TunnelHandle *h{};
|
||||
if (m_->ft_tunnel_create(url.c_str(), &h) != 0 || !h) {
|
||||
|
||||
}
|
||||
h_ = h;
|
||||
|
||||
// C API: ft_status_cb(void* user, int old_status, int new_status, int err, const char* msg)
|
||||
auto tramp = [](void *user, int old_status, int new_status, int err_code, const char *msg) noexcept {
|
||||
auto *self = reinterpret_cast<FileTransferTunnel *>(user);
|
||||
self->status_ = new_status;
|
||||
if (!self->status_cb_) return;
|
||||
try {
|
||||
self->status_cb_(old_status, new_status, err_code, std::string(msg ? msg : ""));
|
||||
} catch (...) {}
|
||||
};
|
||||
if (m_->ft_tunnel_set_status_cb(h_, tramp, this) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_tunnel_set_status_cb failed"); }
|
||||
}
|
||||
|
||||
void FileTransferTunnel::start_connect()
|
||||
{
|
||||
// C API: ft_conn_cb(void* user, int ok, int err, const char* msg)
|
||||
auto tramp = [](void *user, int ok, int ec, const char *msg) noexcept {
|
||||
auto *pcb = reinterpret_cast<ConnectionCb *>(user);
|
||||
if (!pcb) return;
|
||||
try {
|
||||
(*pcb)(ok == 0, ec, std::string(msg ? msg : ""));
|
||||
} catch (...) {}
|
||||
};
|
||||
if (m_->ft_tunnel_start_connect(h_, tramp, &conn_cb_) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_tunnel_start_connect failed"); }
|
||||
}
|
||||
|
||||
bool FileTransferTunnel::sync_start_connect()
|
||||
{
|
||||
return m_->ft_tunnel_sync_connect(h_) == FT_OK;
|
||||
}
|
||||
|
||||
void FileTransferTunnel::on_connection(ConnectionCb cb) { conn_cb_ = std::move(cb); }
|
||||
void FileTransferTunnel::on_status(TunnelStatusCb cb) { status_cb_ = std::move(cb); }
|
||||
|
||||
void FileTransferTunnel::shutdown()
|
||||
{
|
||||
if (m_->ft_tunnel_shutdown) (void) m_->ft_tunnel_shutdown(h_);
|
||||
}
|
||||
|
||||
FileTransferJob::FileTransferJob(FileTransferModule &m, const std::string ¶ms_json) : m_(&m)
|
||||
{
|
||||
FT_JobHandle *h{};
|
||||
if (m_->ft_job_create(params_json.c_str(), &h) != 0 || !h) {
|
||||
|
||||
}
|
||||
h_ = h;
|
||||
|
||||
// C API: ft_job_result_cb(void* user, int tunnel_err, ft_job_result result)
|
||||
auto tramp = [](void *user, ft_job_result r) noexcept {
|
||||
auto *self = reinterpret_cast<FileTransferJob *>(user);
|
||||
if (!self) return;
|
||||
|
||||
try {
|
||||
self->finished_ = true;
|
||||
self->solve_result(r);
|
||||
|
||||
if (self->result_cb_) self->result_cb_(self->res_, self->resp_ec_, self->res_json_, self->res_bin_);
|
||||
self->m_->ft_job_result_destroy(&r);
|
||||
} catch (...) {
|
||||
// swallow
|
||||
}
|
||||
|
||||
try {
|
||||
if (auto *mod = self ? self->m_ : nullptr) {
|
||||
if (mod->ft_job_result_destroy)
|
||||
mod->ft_job_result_destroy(&r);
|
||||
else if (mod->ft_free) {
|
||||
if (r.json) mod->ft_free((void *) r.json);
|
||||
if (r.bin) mod->ft_free((void *) r.bin);
|
||||
}
|
||||
}
|
||||
} catch (...) {}
|
||||
};
|
||||
|
||||
if (m_->ft_job_set_result_cb(h_, tramp, this) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_job_set_result_cb failed"); }
|
||||
}
|
||||
|
||||
void FileTransferJob::on_result(ResultCb cb) { result_cb_ = std::move(cb); }
|
||||
|
||||
bool FileTransferJob::get_result(int &ec, int &resp_ec, std::string &json, std::vector<std::byte> &bin, uint32_t timeout_ms)
|
||||
{
|
||||
if (!h_) throw std::runtime_error("job handle invalid");
|
||||
ft_job_result result;
|
||||
if (m_->ft_job_get_result(h_, timeout_ms, &result) == ft_err::FT_EXCEPTION) return false;
|
||||
solve_result(result);
|
||||
m_->ft_job_result_destroy(&result);
|
||||
ec = res_;
|
||||
resp_ec = res_;
|
||||
json = res_json_;
|
||||
bin = res_bin_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileTransferJob::start_on(FileTransferTunnel &t)
|
||||
{
|
||||
if (!h_) throw std::runtime_error("job handle invalid");
|
||||
if (m_->ft_tunnel_start_job(t.native(), h_) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_tunnel_start_job failed"); }
|
||||
}
|
||||
|
||||
void FileTransferJob::on_msg(MsgCb cb)
|
||||
{
|
||||
msg_cb_ = std::move(cb);
|
||||
if (!h_) return;
|
||||
|
||||
// C API: ft_job_msg_cb(void* user, ft_job_msg msg)
|
||||
auto tramp = [](void *user, ft_job_msg m) noexcept {
|
||||
auto *self = reinterpret_cast<FileTransferJob *>(user);
|
||||
if (!self) return;
|
||||
try {
|
||||
if (self->msg_cb_) { self->msg_cb_(m.kind, std::string(m.json ? m.json : "")); }
|
||||
} catch (...) {}
|
||||
|
||||
try {
|
||||
if (auto *mod = self->m_) {
|
||||
if (mod->ft_job_msg_destroy)
|
||||
mod->ft_job_msg_destroy(&m);
|
||||
else if (mod->ft_free && m.json)
|
||||
mod->ft_free((void *) m.json);
|
||||
}
|
||||
} catch (...) {}
|
||||
};
|
||||
|
||||
if (m_->ft_job_set_msg_cb(h_, tramp, this) == ft_err::FT_EXCEPTION) { throw std::runtime_error("ft_job_set_msg_cb failed"); }
|
||||
}
|
||||
|
||||
bool FileTransferJob::try_get_msg(int &kind, std::string &json)
|
||||
{
|
||||
if (!h_) return false;
|
||||
ft_job_msg m{};
|
||||
int rc = m_->ft_job_try_get_msg(h_, &m);
|
||||
if (rc != 0) return false;
|
||||
|
||||
kind = m.kind;
|
||||
json.assign(m.json ? m.json : "");
|
||||
|
||||
if (m_->ft_job_msg_destroy)
|
||||
m_->ft_job_msg_destroy(&m);
|
||||
else if (m_->ft_free && m.json)
|
||||
m_->ft_free((void *) m.json);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileTransferJob::get_msg(uint32_t timeout_ms, int &kind, std::string &json)
|
||||
{
|
||||
if (!h_) return false;
|
||||
ft_job_msg m{};
|
||||
int rc = m_->ft_job_get_msg(h_, timeout_ms, &m);
|
||||
if (rc != 0) return false;
|
||||
|
||||
kind = m.kind;
|
||||
json.assign(m.json ? m.json : "");
|
||||
|
||||
if (m_->ft_job_msg_destroy)
|
||||
m_->ft_job_msg_destroy(&m);
|
||||
else if (m_->ft_free && m.json)
|
||||
m_->ft_free((void *) m.json);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileTransferJob::solve_result(ft_job_result result)
|
||||
{
|
||||
res_ = result.ec;
|
||||
resp_ec_ = result.resp_ec;
|
||||
|
||||
res_bin_.clear();
|
||||
if (result.bin && result.bin_size) res_bin_.assign(reinterpret_cast<const std::byte *>(result.bin),
|
||||
reinterpret_cast<const std::byte *>(result.bin) + result.bin_size);
|
||||
res_json_.assign(result.json ? result.json : "");
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
254
src/slic3r/Utils/FileTransferUtils.hpp
Normal file
254
src/slic3r/Utils/FileTransferUtils.hpp
Normal file
@@ -0,0 +1,254 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#define FT_CALL __cdecl
|
||||
using ModuleHandle = HMODULE;
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#define FT_CALL
|
||||
using ModuleHandle = void *;
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct ft_job_result
|
||||
{
|
||||
int ec;
|
||||
int resp_ec;
|
||||
const char *json;
|
||||
const void *bin;
|
||||
uint32_t bin_size;
|
||||
};
|
||||
|
||||
struct ft_job_msg
|
||||
{
|
||||
int kind;
|
||||
const char *json;
|
||||
};
|
||||
|
||||
struct FT_TunnelHandle;
|
||||
struct FT_JobHandle;
|
||||
|
||||
typedef enum { FT_OK = 0, FT_EINVAL = -1, FT_ESTATE = -2, FT_EIO = -3, FT_ETIMEOUT = -4, FT_ECANCELLED = -5, FT_EXCEPTION = -6, FT_EUNKNOWN = -128 } ft_err;
|
||||
|
||||
}
|
||||
|
||||
|
||||
inline void *sym_lookup_raw(ModuleHandle mh, const char *name)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return mh ? reinterpret_cast<void *>(::GetProcAddress(mh, name)) : nullptr;
|
||||
#else
|
||||
return mh ? ::dlsym(mh, name) : nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T> inline T sym_lookup(ModuleHandle mh, const char *name)
|
||||
{
|
||||
void *p = sym_lookup_raw(mh, name);
|
||||
if (p) {
|
||||
return reinterpret_cast<T>(p);
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(info) << std::string("symbol not found: ") + name;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
using fn_ft_abi_version = int(FT_CALL *)();
|
||||
using fn_ft_free = void(FT_CALL *)(void *);
|
||||
using fn_ft_job_result_destroy = void(FT_CALL *)(ft_job_result *);
|
||||
using fn_ft_job_msg_destroy = void(FT_CALL *)(ft_job_msg *);
|
||||
|
||||
using fn_ft_tunnel_create = ft_err(FT_CALL *)(const char *url, FT_TunnelHandle **out);
|
||||
using fn_ft_tunnel_retain = void(FT_CALL *)(FT_TunnelHandle *);
|
||||
using fn_ft_tunnel_release = void(FT_CALL *)(FT_TunnelHandle *);
|
||||
using fn_ft_tunnel_start_connect = ft_err(FT_CALL *)(FT_TunnelHandle *, void(FT_CALL *)(void *user, int ok, int err, const char *msg), void *user);
|
||||
using fn_ft_tunnel_sync_connect = ft_err(FT_CALL *)(FT_TunnelHandle *);
|
||||
using fn_ft_tunnel_set_status_cb = ft_err(FT_CALL *)(FT_TunnelHandle *, void(FT_CALL *)(void *user, int old_status, int new_status, int err, const char *msg), void *user);
|
||||
using fn_ft_tunnel_shutdown = ft_err(FT_CALL *)(FT_TunnelHandle *);
|
||||
|
||||
using fn_ft_job_create = ft_err(FT_CALL *)(const char *params_json, FT_JobHandle **out);
|
||||
using fn_ft_job_retain = void(FT_CALL *)(FT_JobHandle *);
|
||||
using fn_ft_job_release = void(FT_CALL *)(FT_JobHandle *);
|
||||
using fn_ft_job_set_result_cb = ft_err(FT_CALL *)(FT_JobHandle *, void(FT_CALL *)(void *user, ft_job_result result), void *user);
|
||||
using fn_ft_job_get_result = ft_err(FT_CALL *)(FT_JobHandle *, uint32_t timeout_ms, ft_job_result *out_result);
|
||||
using fn_ft_tunnel_start_job = ft_err(FT_CALL *)(FT_TunnelHandle *, FT_JobHandle *);
|
||||
using fn_ft_job_cancel = ft_err(FT_CALL *)(FT_JobHandle *);
|
||||
|
||||
using fn_ft_job_msg_destroy = void(FT_CALL *)(ft_job_msg *);
|
||||
using fn_ft_job_set_msg_cb = ft_err(FT_CALL *)(FT_JobHandle *, void(FT_CALL *)(void *user, ft_job_msg msg), void *user);
|
||||
using fn_ft_job_try_get_msg = ft_err(FT_CALL *)(FT_JobHandle *, ft_job_msg *out_msg);
|
||||
using fn_ft_job_get_msg = ft_err(FT_CALL *)(FT_JobHandle *, uint32_t timeout_ms, ft_job_msg *out_msg);
|
||||
|
||||
/// <summary>
|
||||
/// FileTransferModule, support file operations on printer
|
||||
/// </summary>
|
||||
struct FileTransferModule
|
||||
{
|
||||
fn_ft_abi_version ft_abi_version{};
|
||||
fn_ft_free ft_free{};
|
||||
fn_ft_job_result_destroy ft_job_result_destroy{};
|
||||
fn_ft_job_msg_destroy ft_job_msg_destroy{};
|
||||
|
||||
// tunnel(connection)
|
||||
fn_ft_tunnel_create ft_tunnel_create{};
|
||||
fn_ft_tunnel_retain ft_tunnel_retain{};
|
||||
fn_ft_tunnel_release ft_tunnel_release{};
|
||||
fn_ft_tunnel_start_connect ft_tunnel_start_connect{};
|
||||
fn_ft_tunnel_sync_connect ft_tunnel_sync_connect{};
|
||||
fn_ft_tunnel_set_status_cb ft_tunnel_set_status_cb{};
|
||||
fn_ft_tunnel_shutdown ft_tunnel_shutdown{};
|
||||
|
||||
// job(operation)
|
||||
fn_ft_job_create ft_job_create{};
|
||||
fn_ft_job_retain ft_job_retain{};
|
||||
fn_ft_job_release ft_job_release{};
|
||||
fn_ft_job_set_result_cb ft_job_set_result_cb{};
|
||||
fn_ft_job_get_result ft_job_get_result{};
|
||||
fn_ft_tunnel_start_job ft_tunnel_start_job{};
|
||||
fn_ft_job_cancel ft_job_cancel{};
|
||||
|
||||
fn_ft_job_set_msg_cb ft_job_set_msg_cb{};
|
||||
fn_ft_job_try_get_msg ft_job_try_get_msg{};
|
||||
fn_ft_job_get_msg ft_job_get_msg{};
|
||||
|
||||
ModuleHandle networking_{};
|
||||
|
||||
explicit FileTransferModule(ModuleHandle networking_module, int required_abi_version = 1);
|
||||
|
||||
FileTransferModule(const FileTransferModule &) = delete;
|
||||
FileTransferModule &operator=(const FileTransferModule &) = delete;
|
||||
};
|
||||
|
||||
class FileTransferTunnel
|
||||
{
|
||||
public:
|
||||
using ConnectionCb = std::function<void(bool is_success, int err_code, std::string error_msg)>;
|
||||
using TunnelStatusCb = std::function<void(int old_status, int new_status, int err_code, std::string error_msg)>;
|
||||
|
||||
explicit FileTransferTunnel(FileTransferModule &m, const std::string &url);
|
||||
~FileTransferTunnel() { reset(); }
|
||||
|
||||
FileTransferTunnel(const FileTransferTunnel &) = delete;
|
||||
FileTransferTunnel &operator=(const FileTransferTunnel &) = delete;
|
||||
FileTransferTunnel(FileTransferTunnel &&) = delete;
|
||||
FileTransferTunnel &operator=(FileTransferTunnel &&) = delete;
|
||||
|
||||
void start_connect();
|
||||
bool sync_start_connect();
|
||||
void on_connection(ConnectionCb cb);
|
||||
void on_status(TunnelStatusCb cb);
|
||||
|
||||
void shutdown();
|
||||
|
||||
int get_status() const { return status_; }
|
||||
bool check_valid() const { return h_ != nullptr; }
|
||||
FT_TunnelHandle *native() const noexcept { return h_; }
|
||||
|
||||
private:
|
||||
void reset() noexcept
|
||||
{
|
||||
if (h_) {
|
||||
m_->ft_tunnel_release(h_);
|
||||
h_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int status_{};
|
||||
FileTransferModule *m_{};
|
||||
FT_TunnelHandle *h_{};
|
||||
ConnectionCb conn_cb_{};
|
||||
TunnelStatusCb status_cb_{};
|
||||
};
|
||||
|
||||
class FileTransferJob
|
||||
{
|
||||
public:
|
||||
using ResultCb = std::function<void(int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res)>;
|
||||
using MsgCb = std::function<void(int kind, std::string json)>;
|
||||
|
||||
explicit FileTransferJob(FileTransferModule &m, const std::string ¶ms_json);
|
||||
~FileTransferJob() { reset(); }
|
||||
|
||||
FileTransferJob(const FileTransferJob &) = delete;
|
||||
FileTransferJob &operator=(const FileTransferJob &) = delete;
|
||||
FileTransferJob(FileTransferJob &&) = delete;
|
||||
FileTransferJob &operator=(FileTransferJob &&) = delete;
|
||||
|
||||
void on_result(ResultCb cb);
|
||||
|
||||
bool get_result(int &ec, int &resp_ec, std::string &json, std::vector<std::byte> &bin, uint32_t timeout_ms);
|
||||
|
||||
void start_on(FileTransferTunnel &t);
|
||||
|
||||
void on_msg(MsgCb cb);
|
||||
|
||||
bool try_get_msg(int &kind, std::string &json);
|
||||
|
||||
bool get_msg(uint32_t timeout_ms, int &kind, std::string &json);
|
||||
|
||||
FT_JobHandle *native() const noexcept { return h_; }
|
||||
bool check_valid() const { return h_ != nullptr; }
|
||||
bool finished() const { return finished_; }
|
||||
|
||||
void cancel()
|
||||
{
|
||||
if (m_->ft_job_cancel && h_) m_->ft_job_cancel(h_);
|
||||
}
|
||||
|
||||
private:
|
||||
void reset() noexcept
|
||||
{
|
||||
if (h_) {
|
||||
m_->ft_job_release(h_);
|
||||
h_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void solve_result(ft_job_result result);
|
||||
|
||||
FileTransferModule *m_{};
|
||||
FT_JobHandle *h_{};
|
||||
ResultCb result_cb_{};
|
||||
MsgCb msg_cb_{};
|
||||
bool finished_ = false;
|
||||
int res_ = 0;
|
||||
int resp_ec_ = 0;
|
||||
std::string res_json_;
|
||||
std::vector<std::byte> res_bin_;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
inline FileTransferModule *g_mod = nullptr;
|
||||
}
|
||||
|
||||
inline void InitFTModule(ModuleHandle networking_module, int abi_required = 1)
|
||||
{
|
||||
if (detail::g_mod) throw std::runtime_error("Slic3r::InitFTModule called twice");
|
||||
detail::g_mod = new FileTransferModule(networking_module, abi_required);
|
||||
}
|
||||
inline void UnloadFTModule() noexcept
|
||||
{
|
||||
delete detail::g_mod;
|
||||
detail::g_mod = nullptr;
|
||||
}
|
||||
inline FileTransferModule &module()
|
||||
{
|
||||
if (!detail::g_mod) throw std::runtime_error("Slic3r::FTModule not initialized. Call Init() first.");
|
||||
return *detail::g_mod;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,19 +31,44 @@ class AppConfig;
|
||||
class HelioQuery
|
||||
{
|
||||
public:
|
||||
struct SimulationInput
|
||||
{
|
||||
float chamber_temp{ -1 };
|
||||
};
|
||||
|
||||
struct OptimizationInput
|
||||
{
|
||||
bool outer_wall{false};
|
||||
float chamber_temp{ -1 };
|
||||
float min_velocity{ -1 };
|
||||
float max_velocity{ -1 };
|
||||
float min_volumetric_speed{ -1 };
|
||||
float max_volumetric_speed{ -1 };
|
||||
std::array<int, 2> layers_to_optimize = { -1, -1 };
|
||||
|
||||
bool isDefault() {
|
||||
return (min_velocity == -1) &&
|
||||
(max_velocity == -1) &&
|
||||
(min_volumetric_speed == -1) &&
|
||||
(max_volumetric_speed == -1);
|
||||
}
|
||||
};
|
||||
|
||||
struct PresignedURLResult
|
||||
{
|
||||
unsigned status;
|
||||
std::string key;
|
||||
std::string mimeType;
|
||||
std::string url;
|
||||
unsigned status;
|
||||
std::string error;
|
||||
std::string trace_id;
|
||||
};
|
||||
|
||||
struct UploadFileResult
|
||||
{
|
||||
bool success;
|
||||
std::string error;
|
||||
std::string trace_id;
|
||||
};
|
||||
|
||||
struct SupportedData
|
||||
@@ -53,6 +78,13 @@ public:
|
||||
std::string native_name;
|
||||
};
|
||||
|
||||
struct PollResult {
|
||||
std::string status_str;
|
||||
int progress;
|
||||
int sizeKb;
|
||||
bool success;
|
||||
};
|
||||
|
||||
struct CreateGCodeResult
|
||||
{
|
||||
unsigned status;
|
||||
@@ -62,6 +94,12 @@ public:
|
||||
std::string error;
|
||||
vector<std::string> warning_flags;
|
||||
vector<std::string> error_flags;
|
||||
std::string trace_id;
|
||||
|
||||
// V2 API fields
|
||||
float sizeKb;
|
||||
std::string status_str;
|
||||
float progress;
|
||||
};
|
||||
|
||||
struct CreateSimulationResult
|
||||
@@ -71,6 +109,33 @@ public:
|
||||
std::string name;
|
||||
std::string id;
|
||||
std::string error;
|
||||
std::string trace_id;
|
||||
|
||||
void reset() {
|
||||
status = 0;
|
||||
success = false;
|
||||
name = "";
|
||||
id = "";
|
||||
error = "";
|
||||
};
|
||||
};
|
||||
|
||||
struct CreateOptimizationResult
|
||||
{
|
||||
unsigned status;
|
||||
bool success;
|
||||
std::string name;
|
||||
std::string id;
|
||||
std::string error;
|
||||
std::string trace_id;
|
||||
|
||||
void reset() {
|
||||
status = 0;
|
||||
success = false;
|
||||
name = "";
|
||||
id = "";
|
||||
error = "";
|
||||
};
|
||||
};
|
||||
|
||||
struct CheckSimulationProgressResult
|
||||
@@ -82,16 +147,45 @@ public:
|
||||
std::string name;
|
||||
std::string url;
|
||||
std::string error;
|
||||
std::string trace_id;
|
||||
};
|
||||
|
||||
struct CheckOptimizationResult
|
||||
{
|
||||
unsigned status;
|
||||
bool is_finished;
|
||||
float progress;
|
||||
std::string id;
|
||||
std::string name;
|
||||
std::string url;
|
||||
std::string error;
|
||||
std::string trace_id;
|
||||
std::string qualityMeanImprovement;
|
||||
std::string qualityStdImprovement;
|
||||
};
|
||||
|
||||
struct RatingData
|
||||
{
|
||||
int action = 0;
|
||||
std::string qualityMeanImprovement;
|
||||
std::string qualityStdImprovement;
|
||||
};
|
||||
|
||||
|
||||
static std::string get_helio_api_url();
|
||||
static std::string get_helio_pat();
|
||||
static void set_helio_pat(std::string pat);
|
||||
static void request_support_machine(const std::string helio_api_url, const std::string helio_api_key, int page);
|
||||
static void request_support_machine(const std::string helio_api_url, const std::string helio_api_key, int page);
|
||||
static void request_support_material(const std::string helio_api_url, const std::string helio_api_key, int page);
|
||||
static void request_pat_token(std::function<void(std::string)> func);
|
||||
static void request_pat_token(std::function<void(std::string)> func);
|
||||
static void optimization_feedback(const std::string helio_api_url, const std::string helio_api_key, std::string optimization_id, float rating, std::string comment);
|
||||
static PresignedURLResult create_presigned_url(const std::string helio_api_url, const std::string helio_api_key);
|
||||
static UploadFileResult upload_file_to_presigned_url(const std::string file_path_string, const std::string upload_url);
|
||||
|
||||
static PollResult poll_gcode_status(const std::string& helio_api_url,
|
||||
const std::string& helio_api_key,
|
||||
const std::string& gcode_id);
|
||||
|
||||
static CreateGCodeResult create_gcode(const std::string key,
|
||||
const std::string helio_api_url,
|
||||
const std::string helio_api_key,
|
||||
@@ -110,18 +204,56 @@ public:
|
||||
request_support_material(helio_api_url, helio_api_key, 1);
|
||||
}
|
||||
|
||||
/*for helio simulation*/
|
||||
static CreateSimulationResult create_simulation(const std::string helio_api_url,
|
||||
const std::string helio_api_key,
|
||||
const std::string gcode_id,
|
||||
const float initial_room_airtemp,
|
||||
const float layer_threshold,
|
||||
const float object_proximity_airtemp);
|
||||
SimulationInput sinput);
|
||||
|
||||
static void stop_simulation(const std::string helio_api_url,
|
||||
const std::string helio_api_key,
|
||||
const std::string simulation_id);
|
||||
|
||||
static CheckSimulationProgressResult check_simulation_progress(const std::string helio_api_url,
|
||||
const std::string helio_api_key,
|
||||
const std::string simulation_id);
|
||||
|
||||
static std::string generate_graphql_query(const std::string &gcode_id, float temperatureStabilizationHeight = -1, float airTemperatureAboveBuildPlate = -1, float stabilizedAirTemperature = -1);
|
||||
|
||||
/*for helio optimization*/
|
||||
static CreateOptimizationResult create_optimization(const std::string helio_api_url,
|
||||
const std::string helio_api_key,
|
||||
const std::string gcode_id,
|
||||
OptimizationInput oinput);
|
||||
|
||||
static void stop_optimization(const std::string helio_api_url,
|
||||
const std::string helio_api_key,
|
||||
const std::string optimization_id);
|
||||
|
||||
static CheckOptimizationResult check_optimization_progress(const std::string helio_api_url,
|
||||
const std::string helio_api_key,
|
||||
const std::string optimization_id);
|
||||
|
||||
|
||||
static std::string create_optimization_default_get(const std::string helio_api_url, const std::string helio_api_key, const std::string gcode_id);
|
||||
|
||||
|
||||
static std::string generate_default_optimization_query(const std::string& gcode_id);
|
||||
static std::string generate_simulation_graphql_query(const std::string& gcode_id,
|
||||
float temperatureStabilizationHeight = -1,
|
||||
float airTemperatureAboveBuildPlate = -1,
|
||||
float stabilizedAirTemperature = -1);
|
||||
|
||||
static std::string generate_optimization_graphql_query(const std::string& gcode_id,
|
||||
bool outerwall,
|
||||
float temperatureStabilizationHeight = -1,
|
||||
float airTemperatureAboveBuildPlate = -1,
|
||||
float stabilizedAirTemperature = -1,
|
||||
double minVelocity = -1,
|
||||
double maxVelocity = -1,
|
||||
double minExtruderFlowRate = -1,
|
||||
double maxExtruderFlowRate = -1,
|
||||
int layersToOptimizeStart = -1,
|
||||
int layersToOptimizeEnd = -1);
|
||||
static std::string generateTimestampedString()
|
||||
{
|
||||
// Get the current UTC time
|
||||
@@ -136,16 +268,17 @@ public:
|
||||
|
||||
static std::vector<SupportedData> global_supported_printers;
|
||||
static std::vector<SupportedData> global_supported_materials;
|
||||
static std::string last_simulation_trace_id;
|
||||
static std::string last_optimization_trace_id;
|
||||
static double convert_speed(float mm_per_second);
|
||||
static double convert_volume_speed(float mm3_per_second);
|
||||
|
||||
/*user*/
|
||||
static void request_remaining_optimizations(const std::string& helio_api_url, const std::string& helio_api_key, std::function<void(int, int)> func);
|
||||
};
|
||||
|
||||
class HelioBackgroundProcess
|
||||
{
|
||||
public:
|
||||
struct SimulationInput
|
||||
{
|
||||
float chamber_temp{-1};
|
||||
};
|
||||
|
||||
public:
|
||||
enum State {
|
||||
// m_thread is not running yet, or it did not reach the STATE_IDLE yet (it does not wait on the condition yet).
|
||||
@@ -169,19 +302,36 @@ public:
|
||||
std::string printer_id;
|
||||
std::string filament_id;
|
||||
|
||||
//for user input
|
||||
SimulationInput simulation_input_data;
|
||||
int action; //0-simulation 1-optimization
|
||||
|
||||
Slic3r::GCodeProcessorResult* m_gcode_result;
|
||||
/*task data*/
|
||||
HelioQuery::CreateSimulationResult current_simulation_result;
|
||||
HelioQuery::CreateOptimizationResult current_optimization_result;
|
||||
|
||||
//for user input
|
||||
HelioQuery::SimulationInput simulation_input_data;
|
||||
HelioQuery::OptimizationInput optimization_input_data;
|
||||
|
||||
Slic3r::GCodeProcessorResult* m_gcode_result{nullptr};
|
||||
Slic3r::GCodeProcessor m_gcode_processor;
|
||||
Slic3r::GUI::Preview* m_preview;
|
||||
std::function<void()> m_update_function;
|
||||
|
||||
void set_simulation_input_data(SimulationInput data)
|
||||
void set_action(int ac)
|
||||
{
|
||||
action = ac;
|
||||
}
|
||||
|
||||
void set_simulation_input_data(HelioQuery::SimulationInput data)
|
||||
{
|
||||
simulation_input_data = data;
|
||||
}
|
||||
|
||||
void set_optimization_input_data(HelioQuery::OptimizationInput data)
|
||||
{
|
||||
optimization_input_data = data;
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
m_mutex.lock();
|
||||
@@ -222,6 +372,10 @@ public:
|
||||
return state;
|
||||
}
|
||||
|
||||
void stop_current_helio_action();
|
||||
void feedback_current_helio_action(float rating, std::string commend);
|
||||
void clear_helio_file_cache();
|
||||
|
||||
void helio_threaded_process_start(std::mutex& slicing_mutex,
|
||||
std::condition_variable& slicing_condition,
|
||||
BackgroundSlicingProcess::State& slicing_state,
|
||||
@@ -271,12 +425,13 @@ public:
|
||||
|
||||
void set_helio_api_key(std::string api_key);
|
||||
void set_gcode_result(Slic3r::GCodeProcessorResult* gcode_result);
|
||||
void create_simulation_step(HelioQuery::CreateGCodeResult create_gcode_res,
|
||||
std::unique_ptr<GUI::NotificationManager>& notification_manager);
|
||||
void create_simulation_step(HelioQuery::CreateGCodeResult create_gcode_res,std::unique_ptr<GUI::NotificationManager>& notification_manager);
|
||||
void create_optimization_step(HelioQuery::CreateGCodeResult create_gcode_res, std::unique_ptr<GUI::NotificationManager>& notification_manager);
|
||||
void save_downloaded_gcode_and_load_preview(std::string file_download_url,
|
||||
std::string simulated_gcode_path,
|
||||
std::string helio_gcode_path,
|
||||
std::string tmp_path,
|
||||
std::unique_ptr<GUI::NotificationManager>& notification_manager);
|
||||
std::unique_ptr<GUI::NotificationManager>& notification_manager,
|
||||
HelioQuery::RatingData rating_data);
|
||||
|
||||
std::string create_path_for_simulated_gcode(std::string unsimulated_gcode_path)
|
||||
{
|
||||
@@ -292,7 +447,21 @@ public:
|
||||
return (parent / new_filename).string();
|
||||
}
|
||||
|
||||
void load_simulation_to_viwer(std::string file_path, std::string tmp_path);
|
||||
std::string create_path_for_optimization_gcode(std::string unoptimized_gcode_path)
|
||||
{
|
||||
boost::filesystem::path p(unoptimized_gcode_path);
|
||||
|
||||
if (!p.has_filename()) {
|
||||
throw std::runtime_error("Invalid path: No filename present.");
|
||||
}
|
||||
|
||||
boost::filesystem::path parent = p.parent_path();
|
||||
std::string new_filename = "optimized_" + p.filename().string();
|
||||
|
||||
return (parent / new_filename).string();
|
||||
}
|
||||
|
||||
void load_helio_file_to_viwer(std::string file_path, std::string tmp_path, HelioQuery::RatingData rating_data);
|
||||
};
|
||||
} // namespace Slic3r
|
||||
#endif
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
#include "slic3r/Utils/QDTUtil.hpp"
|
||||
#include "NetworkAgent.hpp"
|
||||
|
||||
|
||||
#include "slic3r/Utils/FileTransferUtils.hpp"
|
||||
#include "slic3r/Utils/CertificateVerify.hpp"
|
||||
|
||||
using namespace QDT;
|
||||
|
||||
@@ -76,6 +77,7 @@ func_build_logout_cmd NetworkAgent::build_logout_cmd_ptr = nullptr
|
||||
func_build_login_info NetworkAgent::build_login_info_ptr = nullptr;
|
||||
func_ping_bind NetworkAgent::ping_bind_ptr = nullptr;
|
||||
func_bind_detect NetworkAgent::bind_detect_ptr = nullptr;
|
||||
func_report_consent NetworkAgent::report_consent_ptr = nullptr;
|
||||
func_set_server_callback NetworkAgent::set_server_callback_ptr = nullptr;
|
||||
func_bind NetworkAgent::bind_ptr = nullptr;
|
||||
func_unbind NetworkAgent::unbind_ptr = nullptr;
|
||||
@@ -115,6 +117,7 @@ func_get_model_mall_home_url NetworkAgent::get_model_mall_home_url_ptr =
|
||||
func_get_model_mall_detail_url NetworkAgent::get_model_mall_detail_url_ptr = nullptr;
|
||||
func_get_subtask NetworkAgent::get_subtask_ptr = nullptr;
|
||||
func_get_my_profile NetworkAgent::get_my_profile_ptr = nullptr;
|
||||
func_get_my_token NetworkAgent::get_my_token_ptr = nullptr;
|
||||
func_track_enable NetworkAgent::track_enable_ptr = nullptr;
|
||||
func_track_remove_files NetworkAgent::track_remove_files_ptr = nullptr;
|
||||
func_track_event NetworkAgent::track_event_ptr = nullptr;
|
||||
@@ -171,7 +174,7 @@ std::string NetworkAgent::get_libpath_in_current_directory(std::string library_n
|
||||
}
|
||||
|
||||
|
||||
int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
int NetworkAgent::initialize_network_module(bool using_backup, bool validate_cert)
|
||||
{
|
||||
//int ret = -1;
|
||||
std::string library;
|
||||
@@ -182,6 +185,13 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
if (using_backup) {
|
||||
plugin_folder = plugin_folder/"backup";
|
||||
}
|
||||
std::optional<SignerSummary> self_cert_summary, module_cert_summary;
|
||||
if (validate_cert)
|
||||
self_cert_summary = SummarizeSelf();
|
||||
else
|
||||
BOOST_LOG_TRIVIAL(info) << "wouldn't validate networking dll cert";
|
||||
if (!self_cert_summary)
|
||||
BOOST_LOG_TRIVIAL(info) << "self cert not exist";
|
||||
|
||||
//first load the library
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
@@ -189,13 +199,18 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
wchar_t lib_wstr[128];
|
||||
memset(lib_wstr, 0, sizeof(lib_wstr));
|
||||
::MultiByteToWideChar(CP_UTF8, NULL, library.c_str(), strlen(library.c_str())+1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0]));
|
||||
netwoking_module = LoadLibrary(lib_wstr);
|
||||
/*if (!netwoking_module) {
|
||||
library = std::string(QIDI_NETWORK_LIBRARY) + ".dll";
|
||||
memset(lib_wstr, 0, sizeof(lib_wstr));
|
||||
::MultiByteToWideChar(CP_UTF8, NULL, library.c_str(), strlen(library.c_str()) + 1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0]));
|
||||
if (self_cert_summary) {
|
||||
module_cert_summary = SummarizeModule(library);
|
||||
if (module_cert_summary) {
|
||||
if (IsSamePublisher(*self_cert_summary, *module_cert_summary))
|
||||
netwoking_module = LoadLibrary(lib_wstr);
|
||||
else
|
||||
BOOST_LOG_TRIVIAL(info) << "module is from another publisher:" << module_cert_summary->as_print();
|
||||
}
|
||||
else
|
||||
BOOST_LOG_TRIVIAL(info) << "module_cert is null";
|
||||
} else
|
||||
netwoking_module = LoadLibrary(lib_wstr);
|
||||
}*/
|
||||
if (!netwoking_module) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", try load library directly from current directory");
|
||||
|
||||
@@ -204,10 +219,21 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", can not get path in current directory for %1%") % QIDI_NETWORK_LIBRARY;
|
||||
return -1;
|
||||
}
|
||||
//BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", current path %1%")%library_path;
|
||||
memset(lib_wstr, 0, sizeof(lib_wstr));
|
||||
::MultiByteToWideChar(CP_UTF8, NULL, library_path.c_str(), strlen(library_path.c_str())+1, lib_wstr, sizeof(lib_wstr) / sizeof(lib_wstr[0]));
|
||||
netwoking_module = LoadLibrary(lib_wstr);
|
||||
if (self_cert_summary) {
|
||||
module_cert_summary = SummarizeModule(library_path);
|
||||
if (module_cert_summary) {
|
||||
if (IsSamePublisher(*self_cert_summary, *module_cert_summary))
|
||||
netwoking_module = LoadLibrary(lib_wstr);
|
||||
else
|
||||
BOOST_LOG_TRIVIAL(info) << "module is from another publisher:" << module_cert_summary->as_print();
|
||||
}
|
||||
else
|
||||
BOOST_LOG_TRIVIAL(info) << "module_cert is null";
|
||||
}
|
||||
else
|
||||
netwoking_module = LoadLibrary(lib_wstr);
|
||||
}
|
||||
#else
|
||||
#if defined(__WXMAC__)
|
||||
@@ -216,17 +242,24 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
library = plugin_folder.string() + "/" + std::string("lib") + std::string(QIDI_NETWORK_LIBRARY) + ".so";
|
||||
#endif
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", line %1%, loading network module, using_backup %2%\n")%__LINE__ %using_backup;
|
||||
netwoking_module = dlopen( library.c_str(), RTLD_LAZY);
|
||||
module_cert_summary = SummarizeModule(library);
|
||||
if (self_cert_summary) {
|
||||
module_cert_summary = SummarizeModule(library);
|
||||
if (module_cert_summary) {
|
||||
if (IsSamePublisher(*self_cert_summary, *module_cert_summary))
|
||||
netwoking_module = dlopen(library.c_str(), RTLD_LAZY);
|
||||
else
|
||||
BOOST_LOG_TRIVIAL(info) << "module is from another publisher:" << module_cert_summary->as_print();
|
||||
}
|
||||
else
|
||||
BOOST_LOG_TRIVIAL(info) << "module_cert is null";
|
||||
}
|
||||
else
|
||||
netwoking_module = dlopen( library.c_str(), RTLD_LAZY);
|
||||
if (!netwoking_module) {
|
||||
/*#if defined(__WXMAC__)
|
||||
library = std::string("lib") + QIDI_NETWORK_LIBRARY + ".dylib";
|
||||
#else
|
||||
library = std::string("lib") + QIDI_NETWORK_LIBRARY + ".so";
|
||||
#endif*/
|
||||
//netwoking_module = dlopen( library.c_str(), RTLD_LAZY);
|
||||
char* dll_error = dlerror();
|
||||
printf("error, dlerror is %s\n", dll_error);
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", error, dlerror is %1%")%dll_error;
|
||||
std::string err = dll_error ? std::string(dll_error) : std::string("(null)");
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", error, dlerror is %1%") % err;
|
||||
}
|
||||
printf("after dlopen, network_module is %p\n", netwoking_module);
|
||||
#endif
|
||||
@@ -237,6 +270,9 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", line %1%, successfully loaded library, using_backup %2%, module %3%")%__LINE__ %using_backup %netwoking_module;
|
||||
|
||||
// load file transfer interface
|
||||
InitFTModule(netwoking_module);
|
||||
|
||||
//load the functions
|
||||
check_debug_consistent_ptr = reinterpret_cast<func_check_debug_consistent>(get_network_function("qidi_network_check_debug_consistent"));
|
||||
get_version_ptr = reinterpret_cast<func_get_version>(get_network_function("qidi_network_get_version"));
|
||||
@@ -286,6 +322,7 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
build_login_info_ptr = reinterpret_cast<func_build_login_info>(get_network_function("qidi_network_build_login_info"));
|
||||
ping_bind_ptr = reinterpret_cast<func_ping_bind>(get_network_function("qidi_network_ping_bind"));
|
||||
bind_detect_ptr = reinterpret_cast<func_bind_detect>(get_network_function("qidi_network_bind_detect"));
|
||||
report_consent_ptr = reinterpret_cast<func_report_consent>(get_network_function("qidi_network_report_consent"));
|
||||
set_server_callback_ptr = reinterpret_cast<func_set_server_callback>(get_network_function("qidi_network_set_server_callback"));
|
||||
bind_ptr = reinterpret_cast<func_bind>(get_network_function("qidi_network_bind"));
|
||||
unbind_ptr = reinterpret_cast<func_unbind>(get_network_function("qidi_network_unbind"));
|
||||
@@ -325,6 +362,7 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
get_model_mall_home_url_ptr = reinterpret_cast<func_get_model_mall_home_url>(get_network_function("qidi_network_get_model_mall_home_url"));
|
||||
get_model_mall_detail_url_ptr = reinterpret_cast<func_get_model_mall_detail_url>(get_network_function("qidi_network_get_model_mall_detail_url"));
|
||||
get_my_profile_ptr = reinterpret_cast<func_get_my_profile>(get_network_function("qidi_network_get_my_profile"));
|
||||
get_my_token_ptr = reinterpret_cast<func_get_my_profile>(get_network_function("qidi_network_get_my_token"));
|
||||
track_enable_ptr = reinterpret_cast<func_track_enable>(get_network_function("qidi_network_track_enable"));
|
||||
track_remove_files_ptr = reinterpret_cast<func_track_remove_files>(get_network_function("qidi_network_track_remove_files"));
|
||||
track_event_ptr = reinterpret_cast<func_track_event>(get_network_function("qidi_network_track_event"));
|
||||
@@ -345,6 +383,7 @@ int NetworkAgent::initialize_network_module(bool using_backup)
|
||||
int NetworkAgent::unload_network_module()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", network module %1%")%netwoking_module;
|
||||
UnloadFTModule();
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
if (netwoking_module) {
|
||||
FreeLibrary(netwoking_module);
|
||||
@@ -445,6 +484,7 @@ int NetworkAgent::unload_network_module()
|
||||
get_model_mall_home_url_ptr = nullptr;
|
||||
get_model_mall_detail_url_ptr = nullptr;
|
||||
get_my_profile_ptr = nullptr;
|
||||
get_my_token_ptr = nullptr;
|
||||
track_enable_ptr = nullptr;
|
||||
track_remove_files_ptr = nullptr;
|
||||
track_event_ptr = nullptr;
|
||||
@@ -1018,6 +1058,17 @@ int NetworkAgent::bind_detect(std::string dev_ip, std::string sec_link, detectRe
|
||||
return ret;
|
||||
}
|
||||
|
||||
int NetworkAgent::report_consent(std::string expand)
|
||||
{
|
||||
int ret = 0;
|
||||
if (network_agent && report_consent_ptr) {
|
||||
ret = report_consent_ptr(network_agent, expand);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int NetworkAgent::set_server_callback(OnServerErrFn fn)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -1454,6 +1505,17 @@ int NetworkAgent::get_my_profile(std::string token, unsigned int *http_code, std
|
||||
return ret;
|
||||
}
|
||||
|
||||
int NetworkAgent::get_my_token(std::string ticket, unsigned int* http_code, std::string* http_body)
|
||||
{
|
||||
int ret = 0;
|
||||
if (network_agent && get_my_token_ptr) {
|
||||
ret = get_my_token_ptr(network_agent, ticket, http_code, http_body);
|
||||
if (ret)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format("error network_agnet=%1%, ret = %2%") % network_agent % ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int NetworkAgent::track_enable(bool enable)
|
||||
{
|
||||
enable_track = enable;
|
||||
|
||||
@@ -55,6 +55,7 @@ typedef std::string (*func_build_logout_cmd)(void *agent);
|
||||
typedef std::string (*func_build_login_info)(void *agent);
|
||||
typedef int (*func_ping_bind)(void *agent, std::string ping_code);
|
||||
typedef int (*func_bind_detect)(void *agent, std::string dev_ip, std::string sec_link, detectResult& detect);
|
||||
typedef int (*func_report_consent)(void *agent, std::string expand);
|
||||
typedef int (*func_set_server_callback)(void *agent, OnServerErrFn fn);
|
||||
typedef int (*func_bind)(void *agent, std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn);
|
||||
typedef int (*func_unbind)(void *agent, std::string dev_id);
|
||||
@@ -94,6 +95,7 @@ typedef int (*func_get_subtask)(void *agent, QDTModelTask* task, OnGetSubTaskFn
|
||||
typedef int (*func_get_model_mall_home_url)(void *agent, std::string* url);
|
||||
typedef int (*func_get_model_mall_detail_url)(void *agent, std::string* url, std::string id);
|
||||
typedef int (*func_get_my_profile)(void *agent, std::string token, unsigned int *http_code, std::string *http_body);
|
||||
typedef int (*func_get_my_token)(void *agent, std::string ticket, unsigned int *http_code, std::string *http_body);
|
||||
typedef int (*func_track_enable)(void *agent, bool enable);
|
||||
typedef int (*func_track_remove_files)(void *agent);
|
||||
typedef int (*func_track_event)(void *agent, std::string evt_key, std::string content);
|
||||
@@ -116,7 +118,7 @@ class NetworkAgent
|
||||
|
||||
public:
|
||||
static std::string get_libpath_in_current_directory(std::string library_name);
|
||||
static int initialize_network_module(bool using_backup = false);
|
||||
static int initialize_network_module(bool using_backup = false, bool validate_cert = true);
|
||||
static int unload_network_module();
|
||||
#if defined(_MSC_VER) || defined(_WIN32)
|
||||
static HMODULE get_qidi_source_entry();
|
||||
@@ -172,6 +174,7 @@ public:
|
||||
std::string build_login_info();
|
||||
int ping_bind(std::string ping_code);
|
||||
int bind_detect(std::string dev_ip, std::string sec_link, detectResult& detect);
|
||||
int report_consent(std::string expand);
|
||||
int set_server_callback(OnServerErrFn fn);
|
||||
int bind(std::string dev_ip, std::string dev_id, std::string sec_link, std::string timezone, bool improved, OnUpdateStatusFn update_fn);
|
||||
int unbind(std::string dev_id);
|
||||
@@ -211,6 +214,7 @@ public:
|
||||
int get_model_mall_home_url(std::string* url);
|
||||
int get_model_mall_detail_url(std::string* url, std::string id);
|
||||
int get_my_profile(std::string token, unsigned int* http_code, std::string* http_body);
|
||||
int get_my_token(std::string ticket, unsigned int* http_code, std::string* http_body);
|
||||
int track_enable(bool enable);
|
||||
int track_remove_files();
|
||||
int track_event(std::string evt_key, std::string content);
|
||||
@@ -279,6 +283,7 @@ private:
|
||||
static func_build_login_info build_login_info_ptr;
|
||||
static func_ping_bind ping_bind_ptr;
|
||||
static func_bind_detect bind_detect_ptr;
|
||||
static func_report_consent report_consent_ptr;
|
||||
static func_set_server_callback set_server_callback_ptr;
|
||||
static func_bind bind_ptr;
|
||||
static func_unbind unbind_ptr;
|
||||
@@ -318,6 +323,7 @@ private:
|
||||
static func_get_model_mall_home_url get_model_mall_home_url_ptr;
|
||||
static func_get_model_mall_detail_url get_model_mall_detail_url_ptr;
|
||||
static func_get_my_profile get_my_profile_ptr;
|
||||
static func_get_my_token get_my_token_ptr;
|
||||
static func_track_enable track_enable_ptr;
|
||||
static func_track_remove_files track_remove_files_ptr;
|
||||
static func_track_event track_event_ptr;
|
||||
|
||||
@@ -471,6 +471,8 @@ bool OctoPrint::send_command_to_printer(wxString& msg, wxString commond) const
|
||||
auto url = make_url("printer/gcode/script");
|
||||
bool successful = false;
|
||||
Http http = Http::post(std::move(url));
|
||||
//y72
|
||||
set_auth(http);
|
||||
http.header("Content-Type", "application/json")
|
||||
.set_post_body(json_body)
|
||||
.timeout_connect(4)
|
||||
@@ -495,10 +497,12 @@ bool OctoPrint::send_timelapse_status(wxString& msg, std::string ip, bool status
|
||||
{
|
||||
const char* name = get_name();
|
||||
std::string status_str = status ? "true" : "false";
|
||||
std::string url = (boost::format("http://%1%:7125/machine/timelapse/settings?enabled=%2%") % ip % status_str).str();
|
||||
std::string url = (boost::format("http://%1%/machine/timelapse/settings?enabled=%2%") % ip % status_str).str();
|
||||
bool successful = false;
|
||||
std::string json_body = "{}";
|
||||
Http http = Http::post(std::move(url));
|
||||
//y72
|
||||
set_auth(http);
|
||||
http.header("Content-Type", "application/json")
|
||||
.set_post_body(json_body)
|
||||
.timeout_connect(4)
|
||||
|
||||
@@ -89,26 +89,33 @@ bool json_diff::load_compatible_settings(std::string const &type, std::string co
|
||||
printer_version = version2;
|
||||
}
|
||||
settings_base.clear();
|
||||
std::string config_file = Slic3r::data_dir() + "/printers/" + printer_type + ".json";
|
||||
std::string config_file = Slic3r::resources_dir() + "/printers/" + printer_type + ".json";
|
||||
boost::nowide::ifstream json_file(config_file.c_str());
|
||||
try {
|
||||
json versions;
|
||||
if (json_file.is_open()) {
|
||||
json_file >> versions;
|
||||
for (auto iter = versions.begin(); iter != versions.end(); ++iter) {
|
||||
if (iter.key() > printer_version)
|
||||
if (iter.key() > printer_version) {
|
||||
break;
|
||||
}
|
||||
|
||||
merge_objects(*iter, settings_base);
|
||||
}
|
||||
if (!full_message.empty())
|
||||
if (!full_message.empty()) {
|
||||
diff2all_base_reset(full_message);
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": "<< type << " " << version << ", merged " << versions.dump(1);
|
||||
return true;
|
||||
} else {
|
||||
//BOOST_LOG_TRIVIAL(error) << "load_compatible_settings failed, file = " << config_file;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << type << " " << version << ", failed open file";
|
||||
}
|
||||
} catch (...) {
|
||||
//BOOST_LOG_TRIVIAL(error) << "load_compatible_settings failed, file = " << config_file;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": " << type << " " << version << ", unknown exception";
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -194,9 +201,9 @@ int json_diff::restore_append_objects(json const &in, json &out)
|
||||
for (auto& el: in.items()) {
|
||||
|
||||
if (!out.contains(el.key()) ) {
|
||||
// BOOST_LOG_TRIVIAL(trace) << "json_c append new " << el.key()
|
||||
// << " type: " << el.value().type_name()
|
||||
// << " value: " << el.value();
|
||||
//BOOST_LOG_TRIVIAL(trace) << "json_c append new " << el.key()
|
||||
// << " type: " << el.value().type_name()
|
||||
// << " value: " << el.value();
|
||||
out[el.key()] = el.value();
|
||||
continue;
|
||||
}
|
||||
@@ -205,9 +212,9 @@ int json_diff::restore_append_objects(json const &in, json &out)
|
||||
int recur_ret =
|
||||
restore_append_objects(el.value(), out[el.key()]);
|
||||
if (recur_ret != 0) {
|
||||
// BOOST_LOG_TRIVIAL(trace) << "json_c append obj failed"
|
||||
// << " key: " << el.key()
|
||||
// << " value: " << el.value();
|
||||
//BOOST_LOG_TRIVIAL(trace) << "json_c append obj failed"
|
||||
// << " key: " << el.key()
|
||||
// << " value: " << el.value();
|
||||
return recur_ret;
|
||||
}
|
||||
}
|
||||
@@ -258,10 +265,10 @@ void json_diff::compare_print(json &a, json &b)
|
||||
<< " type: " << e.value().type_name();
|
||||
}
|
||||
if (e.value() != b[e.key()]) {
|
||||
// BOOST_LOG_TRIVIAL(trace) << "json_c compare not equal: key: " << e.key()
|
||||
// << " value: " << e.value();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "json_c compare vs value "
|
||||
// << " vs value: " << b[e.key()];
|
||||
//BOOST_LOG_TRIVIAL(trace) << "json_c compare not equal: key: " << e.key()
|
||||
// << " value: " << e.value();
|
||||
//BOOST_LOG_TRIVIAL(trace) << "json_c compare vs value "
|
||||
// << " vs value: " << b[e.key()];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace QDT {
|
||||
#define QIDI_NETWORK_LIBRARY "qidi_networking"
|
||||
#define QIDI_NETWORK_AGENT_NAME "qidi_network_agent"
|
||||
|
||||
#define QIDI_NETWORK_AGENT_VERSION "02.02.01.62"
|
||||
#define QIDI_NETWORK_AGENT_VERSION "02.03.00.62"
|
||||
|
||||
//iot preset type strings
|
||||
#define IOT_PRINTER_TYPE_STRING "printer"
|
||||
@@ -201,6 +201,7 @@ struct PrintParams {
|
||||
std::string ftp_folder;
|
||||
std::string ftp_file;
|
||||
std::string ftp_file_md5;
|
||||
std::string nozzle_mapping;
|
||||
std::string ams_mapping;
|
||||
std::string ams_mapping2;
|
||||
std::string ams_mapping_info;
|
||||
@@ -235,6 +236,7 @@ struct PrintParams {
|
||||
int auto_flow_cali{ 0 };
|
||||
int auto_offset_cali{ 0 };
|
||||
bool task_ext_change_assist;
|
||||
bool try_emmc_print;
|
||||
};
|
||||
|
||||
struct TaskQueryParams
|
||||
|
||||
Reference in New Issue
Block a user