From b0b78c296c469ec078a8181244e2ebf54322ccd0 Mon Sep 17 00:00:00 2001 From: Ian Chua Date: Wed, 9 Sep 2026 18:35:38 +0800 Subject: [PATCH] feat: check printer storage status before sending --- src/slic3r/Utils/OrcaPrinterAgent.cpp | 74 ++++++++++++++++++--------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/src/slic3r/Utils/OrcaPrinterAgent.cpp b/src/slic3r/Utils/OrcaPrinterAgent.cpp index 4501578e93..3b5ae558ff 100644 --- a/src/slic3r/Utils/OrcaPrinterAgent.cpp +++ b/src/slic3r/Utils/OrcaPrinterAgent.cpp @@ -5,6 +5,7 @@ #include "NetworkAgentFactory.hpp" #include "OrcaCloudServiceAgent.hpp" #include "bambu_networking.hpp" +#include "json_diff.hpp" #include #include #include @@ -145,18 +146,15 @@ std::string extract_line_value(const std::string& body, const std::string& key) // Manual binding uses the OrcaSonar landing page as its sole identity source. // The page returns device_id and may return device_name/model_id. -bool probe_orcasonar_landing_page(const std::string& host, - const std::string& port, - std::string& device_id, - std::string& device_name, - std::string& model_id) +bool probe_orcasonar_landing_page( + const std::string& host, const std::string& port, std::string& device_id, std::string& device_name, std::string& model_id) { device_name = ORCASONAR_FALLBACK; model_id = ORCASONAR_FALLBACK; std::string body; if (fetch_orcasonar_body("http://" + host + ":" + port + "/", body)) { - device_id = extract_line_value(body, "device_id="); + device_id = extract_line_value(body, "device_id="); const std::string name = extract_line_value(body, "device_name="); const std::string model = extract_line_value(body, "model_id="); if (!name.empty()) @@ -173,17 +171,14 @@ bool probe_orcasonar_landing_page(const std::string& host, // SSDP discovery uses the LOCATION URL's UPnP device description as its sole // identity source. OrcaSonar maps device_id/device_name/model_id to UDN, // friendlyName, and modelNumber respectively. -bool parse_orcasonar_device_xml(const std::string& body, - std::string& device_id, - std::string& device_name, - std::string& model_id) +bool parse_orcasonar_device_xml(const std::string& body, std::string& device_id, std::string& device_name, std::string& model_id) { device_name = ORCASONAR_FALLBACK; model_id = ORCASONAR_FALLBACK; try { boost::property_tree::ptree tree; - std::istringstream stream(body); + std::istringstream stream(body); boost::property_tree::read_xml(stream, tree, boost::property_tree::xml_parser::trim_whitespace); const auto device = tree.get_child_optional("root.device"); if (!device) @@ -218,10 +213,7 @@ bool parse_orcasonar_device_xml(const std::string& body, } } -bool probe_orcasonar_device_xml(const std::string& location, - std::string& device_id, - std::string& device_name, - std::string& model_id) +bool probe_orcasonar_device_xml(const std::string& location, std::string& device_id, std::string& device_name, std::string& model_id) { std::string body; return fetch_orcasonar_body(location, body) && parse_orcasonar_device_xml(body, device_id, device_name, model_id); @@ -385,12 +377,12 @@ private: machine["connection_name"] = device_id; machine["dev_ip"] = host + ":" + port; - machine["dev_signal"] = "0"; - machine["connect_type"] = "lan"; - machine["bind_state"] = "free"; - machine["sec_link"] = "secure"; - machine["ssdp_version"] = "v1"; - json = machine.dump(); + machine["dev_signal"] = "0"; + machine["connect_type"] = "lan"; + machine["bind_state"] = "free"; + machine["sec_link"] = "secure"; + machine["ssdp_version"] = "v1"; + json = machine.dump(); return true; } @@ -639,8 +631,7 @@ void OrcaPrinterAgent::set_cloud_agent(std::shared_ptr cloud BOOST_LOG_TRIVIAL(info) << "OrcaPrinterAgent::set_cloud_agent: status callback result=" << callback_result; } -std::unique_ptr -OrcaPrinterAgent::create_camera_signaling_channel(const std::string& dev_id) +std::unique_ptr OrcaPrinterAgent::create_camera_signaling_channel(const std::string& dev_id) { std::lock_guard lock(state_mutex); if (!m_cloud_agent) @@ -1391,6 +1382,43 @@ int OrcaPrinterAgent::start_send_gcode_to_sdcard(PrintParams params, std::string http_error; std::string response_body; + // check if printer has enough storage + Http::get(origin + "/server/files/directory?path=gcodes") + .on_complete([&](std::string body, unsigned status) { + if (body.empty()) { + http_status = 400; + http_error = "Failed to get gcodes directory."; + } + + int free = 0; + + nlohmann::json json = nlohmann::json::parse(body); + if (json.contains("result")) { + json = json["result"]; + if (json.contains("disk_usage")) { + json = json["disk_usage"]; + if (json.contains("free")) + free = json["free"].get(); + } + } + + if (free < file_size) { + http_status = 507; + http_error = "Not enough storage on the printer."; + } + }) + .on_error([&](std::string body, std::string err, unsigned status) { + http_status = status; + http_error = std::move(err); + response_body = std::move(body); + }) + .perform_sync(); + + if (http_status >= 400) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " failed with error code: " << http_status << ", " << http_error; + return BAMBU_NETWORK_ERR_PRINT_SG_UPLOAD_FTP_FAILED; + } + auto http = Http::post(origin + "/server/files/upload"); if (!params.password.empty()) http.header("X-Api-Key", params.password); // trusted LAN facades may not require it; harmless when they do not