Merge branch 'feat/printer-agent-infra' into feat/printer-agent-impl

This commit is contained in:
peachismomo committed 2026-09-24 01:02:59 +08:00
commit 2dcdf49185
14 files changed
+131 -122

No files matched your search

+64 -48
View File
@@ -379,7 +379,7 @@ int MoonrakerPrinterAgent::connect_printer(const PrinterConnectionParams& params
// Launch connection in background thread (capture by value to avoid data races)
{
std::lock_guard<std::recursive_mutex> lock(connect_mutex);
connect_thread = std::thread([this, params, base_url, api_key, gen]() { perform_connection_async(params.dev_id, base_url, api_key, gen); });
connect_thread = std::thread([this, dev_id = params.dev_id, base_url, api_key, gen]() { perform_connection_async(dev_id, base_url, api_key, gen); });
}
return BAMBU_NETWORK_SUCCESS;
@@ -575,12 +575,11 @@ int MoonrakerPrinterAgent::start_local_print(PrintParams params, OnUpdateStatusF
return BAMBU_NETWORK_ERR_CANCELED;
}
// Start print via Moonraker's print API, referencing the file we just uploaded.
// Start print via Moonraker's G-code script endpoint, referencing the file we just uploaded.
if (update_fn)
update_fn(PrintingStageSending, 0, "Starting print...");
std::string start_error;
if (!start_print_file(device_info.base_url, device_info.api_key, upload_filename, start_error)) {
std::string gcode = "SDCARD_PRINT_FILE FILENAME=" + upload_filename;
if (!send_gcode_sync(device_info.dev_id, gcode)) {
return BAMBU_NETWORK_ERR_PRINT_LP_PUBLISH_MSG_FAILED;
}
@@ -1385,12 +1384,8 @@ int MoonrakerPrinterAgent::handle_request(const std::string& dev_id, const std::
}
response["print"]["param"] = gcode;
auto [base_url, api_key] = connection_snapshot();
enqueue_command([this, dev_id, response = std::move(response), base_url = std::move(base_url),
api_key = std::move(api_key)]() mutable {
response["print"]["result"] = send_gcode(dev_id, response["print"]["param"].get<std::string>(), base_url, api_key)
? "success"
: "failed";
send_gcode_async(dev_id, gcode, [this, dev_id, response](bool success) mutable {
response["print"]["result"] = success ? "success" : "failed";
dispatch_message(dev_id, response.dump());
});
return BAMBU_NETWORK_SUCCESS;
@@ -1424,11 +1419,7 @@ int MoonrakerPrinterAgent::handle_request(const std::string& dev_id, const std::
if (json["print"].contains("temp") && json["print"]["temp"].is_number()) {
int temp = json["print"]["temp"].get<int>();
std::string gcode = "SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET=" + std::to_string(temp);
auto [base_url, api_key] = connection_snapshot();
enqueue_command([this, dev_id, gcode = std::move(gcode), base_url = std::move(base_url),
api_key = std::move(api_key)] {
send_gcode(dev_id, gcode, base_url, api_key);
});
send_gcode_async(dev_id, gcode);
return BAMBU_NETWORK_SUCCESS;
}
}
@@ -1443,11 +1434,7 @@ int MoonrakerPrinterAgent::handle_request(const std::string& dev_id, const std::
}
std::string heater = (extruder_idx == 0) ? "extruder" : "extruder" + std::to_string(extruder_idx);
std::string gcode = "SET_HEATER_TEMPERATURE HEATER=" + heater + " TARGET=" + std::to_string(temp);
auto [base_url, api_key] = connection_snapshot();
enqueue_command([this, dev_id, gcode = std::move(gcode), base_url = std::move(base_url),
api_key = std::move(api_key)] {
send_gcode(dev_id, gcode, base_url, api_key);
});
send_gcode_async(dev_id, gcode);
return BAMBU_NETWORK_SUCCESS;
}
}
@@ -1455,10 +1442,7 @@ int MoonrakerPrinterAgent::handle_request(const std::string& dev_id, const std::
// why: no current OrcaSlicer sender emits the "home" discriminator;
// GUI homing uses gcode_line with G28 instead.
if (cmd == "home") {
auto [base_url, api_key] = connection_snapshot();
enqueue_command([this, dev_id, base_url = std::move(base_url), api_key = std::move(api_key)] {
send_gcode(dev_id, "G28", base_url, api_key);
});
send_gcode_async(dev_id, "G28");
return BAMBU_NETWORK_SUCCESS;
}
}
@@ -1504,9 +1488,7 @@ bool MoonrakerPrinterAgent::init_device_info(const std::string& dev_id, const st
device_info.use_ssl = use_ssl;
device_info.model_name = printer_cfg.opt_string("printer_model");
device_info.model_id = preset.get_printer_type(preset_bundle);
device_info.base_url = normalize_base_url(dev_ip, port);
if (use_ssl && boost::istarts_with(device_info.base_url, "http://"))
device_info.base_url.replace(0, 7, "https://");
device_info.base_url = normalize_base_url(use_ssl, dev_ip, port);
device_info.dev_id = dev_id;
device_info.version = "";
device_info.dev_name = device_info.dev_id;
@@ -1913,7 +1895,56 @@ bool MoonrakerPrinterAgent::post_print_action(const std::string& action,
return true;
}
void MoonrakerPrinterAgent::send_gcode_async(const std::string& dev_id, const std::string& gcode,
std::function<void(bool)> on_result) const
{
(void) dev_id;
std::string base_url;
std::string api_key;
{
std::lock_guard<std::recursive_mutex> lock(connect_mutex);
base_url = device_info.base_url;
api_key = device_info.api_key;
}
auto http = Http::post(join_url(base_url, "/printer/gcode/script"));
if (!api_key.empty()) {
http.header("X-Api-Key", api_key);
}
http.header("Content-Type", "application/json")
.set_post_body(nlohmann::json{{"script", gcode}}.dump())
.timeout_connect(5)
.timeout_max(10)
.on_complete([on_result](std::string body, unsigned status_code) {
(void) body;
const bool success = status_code == 200;
if (!success) {
BOOST_LOG_TRIVIAL(error) << "MoonrakerPrinterAgent: send_gcode failed: HTTP error " << status_code;
}
if (on_result) {
on_result(success);
}
})
.on_error([on_result](std::string body, std::string err, unsigned status_code) {
(void) body;
std::string error = err;
if (status_code > 0) {
error += " (HTTP " + std::to_string(status_code) + ")";
}
BOOST_LOG_TRIVIAL(error) << "MoonrakerPrinterAgent: send_gcode failed: " << error;
if (on_result) {
on_result(false);
}
})
.perform();
}
bool MoonrakerPrinterAgent::send_gcode(const std::string& dev_id, const std::string& gcode) const
{
return send_gcode_sync(dev_id, gcode);
}
bool MoonrakerPrinterAgent::send_gcode_sync(const std::string& dev_id, const std::string& gcode) const
{
// why: snapshot then release - see post_print_action.
std::string base_url, api_key;
@@ -3018,7 +3049,7 @@ void MoonrakerPrinterAgent::perform_connection_async(const std::string& dev_id,
if (is_stale()) {
return;
}
device_info.dev_name = fetched_info.dev_name;
device_info.dev_name = fetched_info.dev_name.empty() ? dev_id : fetched_info.dev_name;
device_info.version = fetched_info.version;
device_info.klippy_state = fetched_info.klippy_state;
device_info.nozzle_diameter = fetched_info.nozzle_diameter;
@@ -3066,26 +3097,11 @@ bool MoonrakerPrinterAgent::is_numeric(const std::string& value)
return !value.empty() && std::all_of(value.begin(), value.end(), [](unsigned char c) { return std::isdigit(c) != 0; });
}
std::string MoonrakerPrinterAgent::normalize_base_url(std::string host, const std::string& port)
std::string MoonrakerPrinterAgent::normalize_base_url(bool use_ssl, const std::string& host, const std::string& port)
{
boost::trim(host);
if (host.empty()) {
return "";
}
std::string value = host;
if (is_numeric(port) && value.find("://") == std::string::npos && value.find(':') == std::string::npos) {
value += ":" + port;
}
if (!boost::istarts_with(value, "http://") && !boost::istarts_with(value, "https://")) {
value = "http://" + value;
}
if (value.size() > 1 && value.back() == '/') {
value.pop_back();
}
std::string value = use_ssl ? "https://" : "http://";
value += host;
value += port.empty() ? "" : (":" + port);
return value;
}