From 9676f04cbfc637dee164cdb4f937eaf372b395f4 Mon Sep 17 00:00:00 2001 From: Clifford Garwood Date: Wed, 15 Apr 2026 17:26:58 -0400 Subject: [PATCH] feat: auto-populate physical_extruder_map from AFC extruder_index AFC now publishes an extruder_index field per lane. This lets Moonraker auto-derive physical_extruder_map without user configuration: - Add extruder_index field to AmsTrayData (-1 = not provided) - Parse extruder_index from AFC lane JSON using contains() check since 0 is a valid extruder index (safe_json_int returns 0 for missing fields, which would be ambiguous) - After build_ams_payload, if all trays have extruder_index, derive physical_extruder_map and write it to the printer preset config via CallAfter so IMEX PA and temperature emission use the correct physical extruder qualifier AFC lanes sharing a carriage all report extruder_index=0; independent direct-drive tools on separate carriages report their carriage index. PrintApply.cpp's auto-derive from printer_extruder_id is skipped when physical_extruder_map has more than 1 element, so the AFC-populated map takes precedence. Co-Authored-By: Claude Sonnet 4.6 --- src/slic3r/Utils/MoonrakerPrinterAgent.cpp | 25 ++++++++++++++++++++++ src/slic3r/Utils/MoonrakerPrinterAgent.hpp | 1 + 2 files changed, 26 insertions(+) diff --git a/src/slic3r/Utils/MoonrakerPrinterAgent.cpp b/src/slic3r/Utils/MoonrakerPrinterAgent.cpp index f1d892134b..47921a2440 100644 --- a/src/slic3r/Utils/MoonrakerPrinterAgent.cpp +++ b/src/slic3r/Utils/MoonrakerPrinterAgent.cpp @@ -579,6 +579,27 @@ bool MoonrakerPrinterAgent::fetch_filament_info(std::string dev_id) << (max_lane_index + 1) << " lanes"; int ams_count = (max_lane_index + 4) / 4; build_ams_payload(ams_count, max_lane_index, trays); + + // If every tray reported extruder_index, auto-populate physical_extruder_map + // so IMEX PA and temperature emission use the correct physical extruder qualifier. + // AFC publishes extruder_index=0 for all AFC lanes (they share one carriage) and + // extruder_index=N for independent direct-drive tools on separate carriages. + bool all_have_extruder_index = std::all_of(trays.begin(), trays.end(), + [](const AmsTrayData& t) { return t.extruder_index >= 0; }); + if (all_have_extruder_index) { + std::vector pem(max_lane_index + 1, 0); + for (const auto& tray : trays) + if (tray.slot_index >= 0 && tray.slot_index <= max_lane_index) + pem[tray.slot_index] = tray.extruder_index; + wxTheApp->CallAfter([pem]() { + auto* bundle = GUI::wxGetApp().preset_bundle; + if (!bundle) return; + auto& config = bundle->printers.get_edited_preset().config; + config.set_key_value("physical_extruder_map", new ConfigOptionInts(pem)); + BOOST_LOG_TRIVIAL(info) << "MoonrakerPrinterAgent: auto-populated physical_extruder_map from AFC extruder_index"; + }); + } + return true; } @@ -803,6 +824,10 @@ bool MoonrakerPrinterAgent::fetch_moonraker_filament_data(std::vector(); tray.has_filament = !tray.tray_type.empty(); auto* bundle = GUI::wxGetApp().preset_bundle; tray.tray_info_idx = bundle diff --git a/src/slic3r/Utils/MoonrakerPrinterAgent.hpp b/src/slic3r/Utils/MoonrakerPrinterAgent.hpp index a37a6c3fd6..d8ab18ed2e 100644 --- a/src/slic3r/Utils/MoonrakerPrinterAgent.hpp +++ b/src/slic3r/Utils/MoonrakerPrinterAgent.hpp @@ -90,6 +90,7 @@ protected: // Tray data for AMS payload building struct AmsTrayData { int slot_index = 0; // 0-based slot index + int extruder_index = -1; // Physical extruder index from AFC extruder_index field (-1 = not provided) bool has_filament = false; std::string tray_type; // Material type (e.g., "PLA", "ASA") std::string tray_color; // Raw color (#RRGGBB, 0xRRGGBB, or RRGGBBAA)