_parse_combined_rfid_type()/_match_profile_by_vendor_family() (added in an
earlier nightly) were only ever invoked inside _build_lane_data(), which is
only reached when OrcaSlicer actively polls the Moonraker lane_data endpoint.
The actual MQTT receive path (_on_multicolor_box -> self._ams_slots ->
_push_status_update -> dashboard, and the /kx/filament/slots dashboard API,
and Happy-Hare gate data) never touched this logic at all, so a combined
RFID string like "GEEETECH PLA Bas" kept showing up unmatched everywhere
except the one endpoint nobody was looking at - exactly what @Blaim's
extensive debugging in the issue thread demonstrated.
Centralized the matching into _effective_slot_profile() itself, since all
three real consumers already call it. This fixes the dashboard and gate
data with a single change instead of duplicating the matching logic per
caller (which is what caused the gap in the first place).
While centralizing, found and fixed a related edge case: the stale-profile
guard compared a manual override's material family directly against the
raw combined RFID string, which _material_family() can't parse past the
vendor prefix - a valid manual override on an RFID-tagged slot would have
been incorrectly treated as stale and dropped. Now resolves the plain
material family through the RFID parser first for that comparison.
Also added variant-token disambiguation to _match_profile_by_vendor_family()
per @Blaim's follow-up request: when a vendor has multiple profiles of the
same material family (e.g. "Geeetech PLA Basic" vs. "Geeetech PLA Matte"),
the RFID string's truncated third token ("Bas") is now scored against
candidate profile names instead of always picking the first match.
New tests cover the actual runtime path end-to-end (a realistic
multiColorBox/report payload through _on_multicolor_box, verified against
the /kx/filament/slots response the dashboard consumes) - the previous
test suite only exercised the helper functions and _build_lane_data() in
isolation with hand-set state, which is how this gap went unnoticed.
Anycubic's ACE RFID system concatenates vendor + material + a truncated
serial into one `type` string for custom (third-party) RFID tags, e.g.
"GEEETECH PLA Bas" for a Geeetech PLA spool. The bridge previously
treated this whole string as an unknown material and fell back to a
neutral "Generic <type>" profile, even when the user had already
imported a matching OrcaSlicer profile via the ZIP import feature
(Issue #41) - forcing a manual per-slot reassignment every time that
spool was loaded. Anycubic Slicer Next resolves the same tag correctly.
Add two helpers next to the existing _normalize_material/_material_family:
- _parse_combined_rfid_type(): splits the raw type string, recognizes a
known vendor as the first token (checked against the merged
system+user filament library, so custom vendors like "Geeetech" that
only exist in the user's imported profiles are included), and
extracts the material family from the remainder via the existing
_material_family() prefix search. Returns ("", "") for a vendorless
string like plain "PLA", leaving normal spool reports untouched.
- _match_profile_by_vendor_family(): looks up an imported/system profile
by (vendor, family) rather than exact name, since the truncated RFID
string never contains the full profile name verbatim.
Wired into _build_lane_data() as a third resolution layer, after the
existing manual per-slot override and before the Generic-library
fallback - not persisted to config.ini, so it re-derives fresh on every
call and can't go stale if a differently-tagged spool is loaded later.