mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-01 07:12:07 +00:00
Specify plate index for the 3mf workflow (#14404)
feat: forward plateindex for index-coded .gcode.3mf uploads Gcode inside a .gcode.3mf is index-coded (Metadata/plate_<N>.gcode) and a bundle may carry several, so the upload must name which plate to print — even a single-plate bundle, since its entry is still indexed. A 1-based plate index is stored in PrintHostUpload::extended_info when use_3mf is set; the OctoPrint and Moonraker hosts forward it as a `plateindex` form field. Servers that don't use it ignore the unknown field, so the plain G-code path is unchanged.
This commit is contained in:
@@ -16114,6 +16114,8 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn)
|
|||||||
const bool use_3mf = use_3mf_opt != nullptr && use_3mf_opt->value;
|
const bool use_3mf = use_3mf_opt != nullptr && use_3mf_opt->value;
|
||||||
|
|
||||||
upload_job.upload_data.use_3mf = use_3mf;
|
upload_job.upload_data.use_3mf = use_3mf;
|
||||||
|
// Orca: the concrete plate to export/send (PLATE_CURRENT_IDX resolves to the current plate).
|
||||||
|
const int resolved_plate_idx = plate_idx == PLATE_CURRENT_IDX ? get_partplate_list().get_curr_plate_index() : plate_idx;
|
||||||
|
|
||||||
// Obtain default output path
|
// Obtain default output path
|
||||||
fs::path default_output_file;
|
fs::path default_output_file;
|
||||||
@@ -16203,7 +16205,6 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn)
|
|||||||
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config();
|
DynamicPrintConfig cfg = wxGetApp().preset_bundle->full_config();
|
||||||
const auto* filament_color = dynamic_cast<const ConfigOptionStrings*>(cfg.option("filament_colour"));
|
const auto* filament_color = dynamic_cast<const ConfigOptionStrings*>(cfg.option("filament_colour"));
|
||||||
const auto* filament_id_opt = dynamic_cast<const ConfigOptionStrings*>(cfg.option("filament_ids"));
|
const auto* filament_id_opt = dynamic_cast<const ConfigOptionStrings*>(cfg.option("filament_ids"));
|
||||||
const int resolved_plate_idx = plate_idx == PLATE_CURRENT_IDX ? get_partplate_list().get_curr_plate_index() : plate_idx;
|
|
||||||
auto enrich_project_filaments = [&](std::vector<FilamentInfo>& filaments) {
|
auto enrich_project_filaments = [&](std::vector<FilamentInfo>& filaments) {
|
||||||
for (auto& filament : filaments) {
|
for (auto& filament : filaments) {
|
||||||
if (filament.id < 0)
|
if (filament.id < 0)
|
||||||
@@ -16269,6 +16270,15 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn)
|
|||||||
upload_job.upload_data.group = pDlg->group();
|
upload_job.upload_data.group = pDlg->group();
|
||||||
upload_job.upload_data.storage = pDlg->storage();
|
upload_job.upload_data.storage = pDlg->storage();
|
||||||
upload_job.upload_data.extended_info = pDlg->extendedInfo();
|
upload_job.upload_data.extended_info = pDlg->extendedInfo();
|
||||||
|
// Orca: gcode inside a .gcode.3mf is index-coded (Metadata/plate_<N>.gcode) and a bundle may
|
||||||
|
// carry several of them, so the upload must name which plate to print via a 1-based plateindex.
|
||||||
|
// Even a single-plate bundle needs it, since its gcode entry is still indexed. The host upload
|
||||||
|
// forwards the field and servers that don't use it ignore it. "All plates" points at the
|
||||||
|
// current plate — the bundle still carries every plate's gcode.
|
||||||
|
if (use_3mf) {
|
||||||
|
const int plateindex = (plate_idx == PLATE_ALL_IDX ? get_partplate_list().get_curr_plate_index() : resolved_plate_idx) + 1;
|
||||||
|
upload_job.upload_data.extended_info["plateindex"] = std::to_string(plateindex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show "Is printer clean" dialog for PrusaConnect - Upload and print.
|
// Show "Is printer clean" dialog for PrusaConnect - Upload and print.
|
||||||
@@ -16280,8 +16290,7 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn)
|
|||||||
|
|
||||||
if (use_3mf) {
|
if (use_3mf) {
|
||||||
// Process gcode
|
// Process gcode
|
||||||
const int export_plate_idx = plate_idx == PLATE_CURRENT_IDX ? get_partplate_list().get_curr_plate_index() : plate_idx;
|
const int result = send_gcode(resolved_plate_idx, nullptr);
|
||||||
const int result = send_gcode(export_plate_idx, nullptr);
|
|
||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
wxString msg = _L("Abnormal print file data. Please slice again");
|
wxString msg = _L("Abnormal print file data. Please slice again");
|
||||||
|
|||||||
@@ -237,18 +237,26 @@ bool Moonraker::upload(PrintHostUpload upload_data, ProgressFn progress_fn, Erro
|
|||||||
bool result = true;
|
bool result = true;
|
||||||
std::string uploaded_path;
|
std::string uploaded_path;
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% to %3% (root=%4%, filename=%5%, start_print=%6%)")
|
//ORCA: gcode inside a .gcode.3mf is index-coded (Metadata/plate_<N>.gcode), so the upload names the
|
||||||
|
// plate via a 1-based `plateindex` (set only in the .3mf path, see Plater::send_gcode_legacy);
|
||||||
|
// servers that don't use it ignore the unknown form field.
|
||||||
|
const std::string plateindex = upload_data.extended("plateindex");
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% to %3% (root=%4%, filename=%5%, plateindex=%6%, start_print=%7%)")
|
||||||
% name
|
% name
|
||||||
% upload_data.source_path
|
% upload_data.source_path
|
||||||
% url
|
% url
|
||||||
% root
|
% root
|
||||||
% upload_filename.string()
|
% upload_filename.string()
|
||||||
|
% (plateindex.empty() ? "-" : plateindex)
|
||||||
% (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false");
|
% (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false");
|
||||||
|
|
||||||
auto http = Http::post(std::move(url));
|
auto http = Http::post(std::move(url));
|
||||||
set_auth(http);
|
set_auth(http);
|
||||||
http.form_add("root", root)
|
http.form_add("root", root);
|
||||||
.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
|
if (!plateindex.empty())
|
||||||
|
http.form_add("plateindex", plateindex);
|
||||||
|
http.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
|
||||||
.on_complete([&](std::string body, unsigned status) {
|
.on_complete([&](std::string body, unsigned status) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: upload HTTP %2%: %3%") % name % status % body;
|
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: upload HTTP %2%: %3%") % name % status % body;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -345,13 +345,15 @@ bool OctoPrint::upload_inner_with_resolved_ip(PrintHostUpload upload_data, Progr
|
|||||||
|
|
||||||
info_fn(L"resolve", boost::nowide::widen(url));
|
info_fn(L"resolve", boost::nowide::widen(url));
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%")
|
const std::string plateindex = upload_data.extended("plateindex");
|
||||||
|
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%, plateindex: %7%")
|
||||||
% name
|
% name
|
||||||
% upload_data.source_path
|
% upload_data.source_path
|
||||||
% url
|
% url
|
||||||
% upload_filename.string()
|
% upload_filename.string()
|
||||||
% upload_parent_path.string()
|
% upload_parent_path.string()
|
||||||
% (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false");
|
% (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
|
||||||
|
% (plateindex.empty() ? "-" : plateindex);
|
||||||
|
|
||||||
auto http = Http::post(url);//std::move(url));
|
auto http = Http::post(url);//std::move(url));
|
||||||
// "Host" header is necessary here. We have resolved IP address and subsituted it into "url" variable.
|
// "Host" header is necessary here. We have resolved IP address and subsituted it into "url" variable.
|
||||||
@@ -362,8 +364,13 @@ bool OctoPrint::upload_inner_with_resolved_ip(PrintHostUpload upload_data, Progr
|
|||||||
http.header("Host", Http::get_host_header_value(m_host));
|
http.header("Host", Http::get_host_header_value(m_host));
|
||||||
set_auth(http);
|
set_auth(http);
|
||||||
http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
|
http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
|
||||||
.form_add("path", upload_parent_path.string()) // XXX: slashes on windows ???
|
.form_add("path", upload_parent_path.string()); // XXX: slashes on windows ???
|
||||||
.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
|
//ORCA: gcode inside a .gcode.3mf is index-coded (Metadata/plate_<N>.gcode), so the upload names the
|
||||||
|
// plate via a 1-based `plateindex` (see Plater::send_gcode_legacy); servers that don't use it
|
||||||
|
// ignore the unknown form field.
|
||||||
|
if (!plateindex.empty())
|
||||||
|
http.form_add("plateindex", plateindex);
|
||||||
|
http.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
|
||||||
|
|
||||||
.on_complete([&](std::string body, unsigned status) {
|
.on_complete([&](std::string body, unsigned status) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body;
|
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body;
|
||||||
@@ -429,13 +436,15 @@ bool OctoPrint::upload_inner_with_host(PrintHostUpload upload_data, ProgressFn p
|
|||||||
}
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%")
|
const std::string plateindex = upload_data.extended("plateindex");
|
||||||
|
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%, plateindex: %7%")
|
||||||
% name
|
% name
|
||||||
% upload_data.source_path
|
% upload_data.source_path
|
||||||
% url
|
% url
|
||||||
% upload_filename.string()
|
% upload_filename.string()
|
||||||
% upload_parent_path.string()
|
% upload_parent_path.string()
|
||||||
% (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false");
|
% (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
|
||||||
|
% (plateindex.empty() ? "-" : plateindex);
|
||||||
|
|
||||||
auto http = Http::post(std::move(url));
|
auto http = Http::post(std::move(url));
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -449,8 +458,13 @@ bool OctoPrint::upload_inner_with_host(PrintHostUpload upload_data, ProgressFn p
|
|||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
set_auth(http);
|
set_auth(http);
|
||||||
http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
|
http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
|
||||||
.form_add("path", upload_parent_path.string()) // XXX: slashes on windows ???
|
.form_add("path", upload_parent_path.string()); // XXX: slashes on windows ???
|
||||||
.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
|
//ORCA: gcode inside a .gcode.3mf is index-coded (Metadata/plate_<N>.gcode), so the upload names the
|
||||||
|
// plate via a 1-based `plateindex` (see Plater::send_gcode_legacy); servers that don't use it
|
||||||
|
// ignore the unknown form field.
|
||||||
|
if (!plateindex.empty())
|
||||||
|
http.form_add("plateindex", plateindex);
|
||||||
|
http.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
|
||||||
.on_complete([&](std::string body, unsigned status) {
|
.on_complete([&](std::string body, unsigned status) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body;
|
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ ENABLE_ENUM_BITMASK_OPERATORS(PrintHostPostUploadAction);
|
|||||||
|
|
||||||
struct PrintHostUpload
|
struct PrintHostUpload
|
||||||
{
|
{
|
||||||
bool use_3mf;
|
bool use_3mf { false };
|
||||||
boost::filesystem::path source_path;
|
boost::filesystem::path source_path;
|
||||||
boost::filesystem::path upload_path;
|
boost::filesystem::path upload_path;
|
||||||
|
|
||||||
@@ -40,6 +40,13 @@ struct PrintHostUpload
|
|||||||
|
|
||||||
// Some extended parameters for different upload methods.
|
// Some extended parameters for different upload methods.
|
||||||
std::map<std::string, std::string> extended_info;
|
std::map<std::string, std::string> extended_info;
|
||||||
|
|
||||||
|
// Safe accessor for an extended_info entry; returns `def` when the key is absent.
|
||||||
|
std::string extended(const std::string &key, const std::string &def = {}) const
|
||||||
|
{
|
||||||
|
auto it = extended_info.find(key);
|
||||||
|
return it != extended_info.end() ? it->second : def;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PrintHost
|
class PrintHost
|
||||||
|
|||||||
Reference in New Issue
Block a user