From df80c9ae220a43257f216c1765f81c0ff1dcd1a6 Mon Sep 17 00:00:00 2001 From: Hanif Koh Date: Sun, 18 Oct 2026 15:59:41 +0800 Subject: [PATCH] Translate H2C Nozzle Rack Filament IDs at the Printer Boundary The Bambu payload rewrite only matched tray_info_idx, filament_id and filamentId. The H2C nozzle rack carries filament ids under cate (the auto nozzle mapping request) and fila_id (the rack status), so the printer got Orca's OF ids for the filaments and its own ids back for the nozzles in the same request, and the device tab could not name a rack nozzle's filament. Add both keys to one shared list used by the rewrite and its pre-check. --- docs/HLSD/filament_id.md | 7 +++++-- src/slic3r/Utils/BBLPrinterAgent.cpp | 15 +++++++++---- tests/slic3rutils/test_bambu_filament_ids.cpp | 21 +++++++++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/docs/HLSD/filament_id.md b/docs/HLSD/filament_id.md index 122dfb6fdb..555a5d6ad5 100644 --- a/docs/HLSD/filament_id.md +++ b/docs/HLSD/filament_id.md @@ -350,8 +350,11 @@ identity default and translates nothing. `NetworkAgent` forwards both to the liv comparison sites below reach them through `wxGetApp().getAgent()` and leave an id untranslated while no agent is live. Whole documents are Bambu's business alone: `BBLPrinterAgent::to_orca_payload` and `from_orca_payload` rewrite every string under -`tray_info_idx`, `filament_id` or `filamentId` at any depth; text that does not parse, or carries -none of those keys, comes back unchanged. The map is loaded once, lazily; a missing or malformed +`tray_info_idx`, `filament_id`, `filamentId`, `cate` or `fila_id` at any depth; text that does not +parse, or carries none of those keys, comes back unchanged. The last two are the H2C nozzle rack's: +`cate` in the auto nozzle mapping request, `fila_id` in the rack status. A new Bambu message that +carries a filament id under another key needs that key added to `filament_id_keys`, or the id +crosses the boundary untranslated. The map is loaded once, lazily; a missing or malformed file degrades to identity with a log line rather than failing. | Boundary | Where it translates | diff --git a/src/slic3r/Utils/BBLPrinterAgent.cpp b/src/slic3r/Utils/BBLPrinterAgent.cpp index 7fde77a075..30fd075fc4 100644 --- a/src/slic3r/Utils/BBLPrinterAgent.cpp +++ b/src/slic3r/Utils/BBLPrinterAgent.cpp @@ -7,6 +7,8 @@ #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/DeviceCore/DevManager.h" +#include +#include #include #include #include @@ -16,6 +18,7 @@ #include #include #include +#include #include #include using json = nlohmann::json; @@ -64,12 +67,16 @@ const BambuFilamentIdMap& bambu_filament_id_map() return map; } -// Rewrites every string under "tray_info_idx", "filament_id" or "filamentId", at any depth, in place. +// Keys whose string value is a filament id. "cate" and "fila_id" are the H2C nozzle rack's: the +// auto nozzle mapping request and the rack status in the push message. +constexpr std::array filament_id_keys{"tray_info_idx", "filament_id", "filamentId", "cate", "fila_id"}; + +// Rewrites every string under a filament id key, at any depth, in place. void rewrite_filament_ids(json& j, const std::unordered_map& map) { if (j.is_object()) { for (auto& [key, value] : j.items()) { - if (value.is_string() && (key == "tray_info_idx" || key == "filament_id" || key == "filamentId")) { + if (value.is_string() && std::find(filament_id_keys.begin(), filament_id_keys.end(), key) != filament_id_keys.end()) { auto it = map.find(value.get_ref()); if (it != map.end()) value = it->second; @@ -84,8 +91,8 @@ void rewrite_filament_ids(json& j, const std::unordered_map& map) { - if (map.empty() || (text.find("tray_info_idx") == std::string::npos && text.find("filament_id") == std::string::npos && - text.find("filamentId") == std::string::npos)) + if (map.empty() || std::none_of(filament_id_keys.begin(), filament_id_keys.end(), + [&text](std::string_view key) { return text.find(key) != std::string::npos; })) return text; // nothing to map, skip the parse (moved, not copied) try { json j = json::parse(text); diff --git a/tests/slic3rutils/test_bambu_filament_ids.cpp b/tests/slic3rutils/test_bambu_filament_ids.cpp index 7d9e0df1f1..fef2c8a224 100644 --- a/tests/slic3rutils/test_bambu_filament_ids.cpp +++ b/tests/slic3rutils/test_bambu_filament_ids.cpp @@ -81,3 +81,24 @@ TEST_CASE("Payload rewrite covers nested trays, calibration lists and mapping in CHECK(BBLPrinterAgent::from_orca_payload("not json") == "not json"); CHECK(BBLPrinterAgent::from_orca_payload(R"({"print":{"command":"pushall"}})") == R"({"print":{"command":"pushall"}})"); } + +TEST_CASE("Payload rewrite covers the nozzle rack status and the auto nozzle mapping request", "[BambuFilamentIds]") +{ + const ScopedRepoResourcesDir repo_resources; + const std::string petg_hf = orca_id_of("GFG96"); + + const std::string rack_status = + R"({"print":{"device":{"nozzle":{"info":[{"id":16,"fila_id":"GFG96","color_m":"FFFFFFFF"},{"id":17,"fila_id":"P22f54c9"}]}}}})"; + json inbound = json::parse(BBLPrinterAgent::to_orca_payload(rack_status)); + CHECK(inbound["print"]["device"]["nozzle"]["info"][0]["fila_id"] == petg_hf); + CHECK(inbound["print"]["device"]["nozzle"]["info"][1]["fila_id"] == "P22f54c9"); // user id: untouched + + const std::string request = R"({"print":{"command":"get_auto_nozzle_mapping","ams_mapping":[65535,65024],)" + R"("fila_info":[{"id":2,"cate":")" + petg_hf + R"(","color":"FFFFFFFF"}],)" + R"("nozzle_info":[{"pos":16,"cate":")" + petg_hf + R"(","color":"FFFFFFFF"},{"pos":1,"cate":""}]}})"; + json outbound = json::parse(BBLPrinterAgent::from_orca_payload(request)); + CHECK(outbound["print"]["fila_info"][0]["cate"] == "GFG96"); + CHECK(outbound["print"]["nozzle_info"][0]["cate"] == "GFG96"); + CHECK(outbound["print"]["nozzle_info"][1]["cate"] == ""); // empty nozzle + CHECK(outbound["print"]["ams_mapping"] == json::parse("[65535,65024]")); +}