feat(moonraker): Bridge-Filament-Hint (tray_info_idx + vendor) respektieren

KX-Bridge sendet bereits konkrete Filament-IDs und Vendor-Hints im
AMS-JSON, aber MoonrakerPrinterAgent überschreibt sie unbedingt mit
filament_id_by_type() → erstes sichtbares Preset alphabetisch gewinnt.

Patch:
- AmsTrayData um filament_vendor erweitert
- Liest tray_info_idx + filament_vendor aus Bridge-JSON
- Wenn tray_info_idx leer + vendor vorhanden: Vendor+Type+Color-Match
  (gleiche Logik wie SnapmakerPrinterAgent)
- Sonst: alter filament_id_by_type-Fallback (unverändertes Verhalten)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
viewit
2026-05-29 20:42:10 +02:00
parent 00271d7130
commit 3d0aeb3877
2 changed files with 58 additions and 3 deletions

View File

@@ -37,6 +37,48 @@ struct WsEndpoint
bool secure = false;
};
// Find best-matching visible filament preset by vendor + type + color.
// Same algorithm as SnapmakerPrinterAgent's helper. Allows the KX-Bridge
// (which knows the user's slot brand selection) to direct OrcaSlicer to a
// specific preset instead of falling back to "first sichtbares PETG" lookup.
std::string find_closest_color_preset_by_vendor_and_type(const Slic3r::PresetCollection& filaments,
const std::string& vendor_name,
const std::string& filament_type,
const std::string& color_rgba)
{
std::string best_match_id = "";
int best_color_distance = 0xffffffff;
if (vendor_name.empty() || filament_type.empty()) return best_match_id;
auto parse_color = [](const std::string& s) -> unsigned int {
if (s.empty()) return 0;
std::string h = s;
if (!h.empty() && h.front() == '#') h.erase(0, 1);
if (h.size() >= 8) h = h.substr(0, 6); // strip alpha
try { return std::stoul(h, nullptr, 16); } catch (...) { return 0; }
};
unsigned int target = parse_color(color_rgba);
for (const auto& p : filaments.get_presets()) {
if (!(p.is_visible && p.is_compatible)) continue;
if (filaments.get_preset_base(p) != &p) continue;
if (p.config.opt_string("filament_vendor", 0u) != vendor_name) continue;
if (p.config.opt_string("filament_type", 0u) != filament_type) continue;
unsigned int pc = parse_color(p.config.opt_string("default_filament_colour", 0u));
int dr = ((target ) & 0xff) - ((pc ) & 0xff);
int dg = ((target >> 8) & 0xff) - ((pc >> 8) & 0xff);
int db = ((target >> 16) & 0xff) - ((pc >> 16) & 0xff);
unsigned int distance = dr * dr + dg * dg + db * db;
if (distance < (unsigned int)best_color_distance) {
best_color_distance = (int)distance;
best_match_id = p.filament_id;
}
}
return best_match_id;
}
bool parse_ws_endpoint(const std::string& base_url, WsEndpoint& endpoint)
{
if (base_url.empty()) {
@@ -806,10 +848,22 @@ bool MoonrakerPrinterAgent::fetch_moonraker_filament_data(std::vector<AmsTrayDat
tray.nozzle_temp = safe_json_int(lane_obj, "nozzle_temp");
tray.has_filament = !tray.tray_type.empty();
has_populated_lane = has_populated_lane || tray.has_filament;
// Bridge-Hints: tray_info_idx (konkrete Filament-ID) + filament_vendor.
// KX-Bridge sendet beide, wenn der User in der Bridge-UI ein konkretes
// Slot-Profil gewählt hat (Polymaker/eSUN/…).
tray.tray_info_idx = safe_json_string(lane_obj, "tray_info_idx");
tray.filament_vendor = safe_json_string(lane_obj, "filament_vendor");
auto* bundle = GUI::wxGetApp().preset_bundle;
tray.tray_info_idx = bundle
? bundle->filaments.filament_id_by_type(tray.tray_type)
: map_filament_type_to_generic_id(tray.tray_type);
if (tray.tray_info_idx.empty() && bundle && !tray.filament_vendor.empty()) {
std::string mid = find_closest_color_preset_by_vendor_and_type(
bundle->filaments, tray.filament_vendor, tray.tray_type, tray.tray_color);
if (!mid.empty()) tray.tray_info_idx = mid;
}
if (tray.tray_info_idx.empty()) {
tray.tray_info_idx = bundle
? bundle->filaments.filament_id_by_type(tray.tray_type)
: map_filament_type_to_generic_id(tray.tray_type);
}
max_lane_index = std::max(max_lane_index, lane_index);
trays.push_back(tray);

View File

@@ -94,6 +94,7 @@ protected:
std::string tray_type; // Material type (e.g., "PLA", "ASA")
std::string tray_color; // Raw color (#RRGGBB, 0xRRGGBB, or RRGGBBAA)
std::string tray_info_idx; // Setting ID (optional)
std::string filament_vendor; // Vendor hint from bridge (optional, KX-Bridge sendet das)
int bed_temp = 0; // Optional
int nozzle_temp = 0; // Optional
};