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]")); +}