CrealityPrint: add multi-color print protocol for K2 Plus

For supported models, start_print() sends colorMatch (filament-to-slot
mapping) followed by multiColorPrint (with optional calibration via
enableSelfTest) instead of the legacy opGcodeFile command. The dialog
passes color mapping and calibration settings through extended_info.

Signed-off-by: Igor Mammedov <niallain@gmail.com>
---
v4:
- Skip "path" form field in multipart upload for multi-color printers
  (extra field breaks K2 Plus firmware parser)
- Use fire-and-forget ws.write() for colorMatch and multiColorPrint
  instead of ws_send_and_read() (printer sends response asynchronously)
This commit is contained in:
Igor Mammedov
2026-04-27 19:29:43 +02:00
parent 9204e4f6a4
commit 38047e8ae8
2 changed files with 69 additions and 14 deletions

View File

@@ -140,15 +140,16 @@ bool CrealityPrint::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn,
auto http = Http::post(url); // std::move(url));
set_auth(http);
http.form_add("path", upload_parent_path.string())
.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
if (!supports_multi_color_print())
http.form_add("path", upload_parent_path.string());
http.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
.on_complete([&](std::string body, unsigned status) {
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body;
if (upload_data.post_action == PrintHostPostUploadAction::StartPrint) {
wxString errormsg;
if (!start_print(errormsg, safe_filename(upload_filename.string()))) {
if (!start_print(errormsg, safe_filename(upload_filename.string()), upload_data.extended_info)) {
error_fn(std::move(errormsg));
res = false;
}
@@ -278,28 +279,81 @@ std::string CrealityPrint::query_boxes_info() const
}
}
bool CrealityPrint::start_print(wxString &msg, const std::string &filename) const
bool CrealityPrint::start_print(wxString &msg, const std::string &filename, const std::map<std::string, std::string>& extended_info) const
{
try {
const std::string gcode_path = "/mnt/UDISK/printer_data/gcodes/" + filename;
net::io_context ioc;
websocket::stream<beast::tcp_stream> ws{ioc};
ws_connect(ioc, ws, m_host, "9999");
json j2 = {
{ "method", "set" },
{
"params", {
{ "opGcodeFile", "printprt:/usr/data/printer_data/gcodes/" + filename }
if (supports_multi_color_print()) {
// Build colorMatch list from the mapping provided by the dialog
json color_list = json::array();
for (int i = 0; ; i++) {
auto it = extended_info.find("colorMatch_" + std::to_string(i));
if (it == extended_info.end())
break;
// Value format: "toolId\ttype\tcolor\tboxId\tmaterialId"
auto val = it->second;
std::vector<std::string> parts;
std::istringstream iss(val);
std::string part;
while (std::getline(iss, part, '\t'))
parts.push_back(part);
if (parts.size() >= 5) {
color_list.push_back({
{"id", parts[0]},
{"type", parts[1]},
{"color", parts[2]},
{"boxId", std::stoi(parts[3])},
{"materialId", std::stoi(parts[4])}
});
}
}
};
ws.write(net::buffer(to_string(j2)));
json color_match = {
{"method", "set"},
{"params", {
{"colorMatch", {
{"path", gcode_path},
{"list", color_list}
}}
}}
};
ws.write(net::buffer(to_string(color_match)));
beast::flat_buffer buffer;
// Read enableSelfTest from extended_info, default to 0 (calibration off)
int enable_self_test = 0;
auto it = extended_info.find("enableSelfTest");
if (it != extended_info.end())
enable_self_test = std::stoi(it->second);
ws.read(buffer);
json multi_color_print = {
{"method", "set"},
{"params", {
{"multiColorPrint", {
{"gcode", gcode_path},
{"enableSelfTest", enable_self_test}
}}
}}
};
ws.write(net::buffer(to_string(multi_color_print)));
} else {
json cmd = {
{"method", "set"},
{"params", {
{"opGcodeFile", "printprt:/usr/data/printer_data/gcodes/" + filename}
}}
};
ws.write(net::buffer(to_string(cmd)));
beast::flat_buffer buffer;
ws.read(buffer);
}
ws.close(websocket::close_code::normal);
return true;
} catch(std::exception const& e) {
BOOST_LOG_TRIVIAL(error) << "CrealityPrint: Error starting print: " << e.what();

View File

@@ -1,6 +1,7 @@
#ifndef slic3r_CrealityPrint_hpp_
#define slic3r_CrealityPrint_hpp_
#include <map>
#include <string>
#include <wx/string.h>
#include <boost/optional.hpp>
@@ -44,7 +45,7 @@ private:
mutable std::string m_model;
std::string make_url(const std::string& path) const;
bool start_print(wxString& msg, const std::string& path) const;
bool start_print(wxString& msg, const std::string& filename, const std::map<std::string, std::string>& extended_info) const;
std::string safe_filename(const std::string& filename) const;
void query_model() const;
};