Skip to content

[Fix] Dual-UID spool identification, use tray_uuid end-to-end#1200

Open
Keybored02 wants to merge 13 commits into
maziggy:devfrom
Keybored02:fix/tray_uuid
Open

[Fix] Dual-UID spool identification, use tray_uuid end-to-end#1200
Keybored02 wants to merge 13 commits into
maziggy:devfrom
Keybored02:fix/tray_uuid

Conversation

@Keybored02

Copy link
Copy Markdown
Collaborator

Description

Adds a secondary tag_uid_2 field so a spool can be identified by two different hardware UIDs (different physical tags). Fixes tray_uuid being silently dropped when adding a new spool through SpoolBuddy — it's now saved and used as the primary match identifier end-to-end. Also fixes the spool card staying visible on the SpoolBuddy dashboard after removing a freshly-added spool.

Related Issue

Fixes #984

Documentation

Companion docs PRs (delete lines that don't apply):

Pick one:

  • [] Docs PR(s) linked above
  • No docs update required — reason: backend update and behavior fix

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Code refactoring
  • Performance improvement
  • Test addition or update

Changes Made

  1. Dual tag UID support (tag_uid_2)

Adds an optional secondary hardware UID column per spool, to handle the real-world case where the same physical tag is reported with a different first byte by different NFC reader hardware. The second slot is strictly opt-in — it is never auto-assigned; it can only be set explicitly via the PATCH /spools/{id}/link-tag API or the spool form.

New tag_uid_2 VARCHAR(16) column on the spool table with an inline _safe_execute migration
All matching logic (get_spool_by_tag, fuzzy fallback) searches both columns transparently via a shared _fuzzy_uid_match() helper
Conflict checks in the link-tag route cover both columns on active and archived spools
Frontend displays the primary UID with both in the tooltip; "tagged/untagged" filters and the write-tag page check both columns

  1. tray_uuid saved end-to-end through SpoolBuddy

Previously, when a Bambu Lab spool was scanned by SpoolBuddy and the user created a new inventory entry or linked it to an existing spool, the tray_uuid (read from MIFARE Classic block 9) was silently dropped. This meant subsequent scans matched by hardware UID only, losing the more-reliable UUID-based matching.

spoolbuddy_unknown_tag and spoolbuddy_tag_matched WebSocket broadcasts now include tray_uuid
useSpoolBuddyState carries tray_uuid through state (unknownTrayUuid, currentTrayUuid)
SpoolBuddyDashboard tracks displayedTrayUuid alongside displayedTagId, and passes it to createSpool and linkTagToSpool calls
tag_type is set to 'bambulab' (not 'generic') when a tray_uuid is present

  1. Dashboard card cleared on tag removal

After a quick-add, removing the spool from the scale/reader left the card visible. The tag-removal useEffect only cleared state when hiddenTagId was set (i.e. the user had closed the card), so a freshly-added spool — where the card was never manually closed — was never cleared on physical removal.

The else-branch now clears displayedTagId/displayedTrayUuid whenever either is non-null, unconditionally

Screenshots

Testing

  • I have tested this on my local machine
  • I have tested with my printer model: H2C

Checklist

  • My code follows the project's coding style
  • I have commented my code where necessary
  • My changes generate no new warnings
  • I have tested my changes thoroughly

Additional Notes

@Keybored02
Keybored02 requested a review from maziggy as a code owner May 3, 2026 08:17
@maziggy

maziggy commented May 3, 2026

Copy link
Copy Markdown
Owner

Not sure if this is the right moment to add it. Please align with @netscout2001

@Keybored02

Copy link
Copy Markdown
Collaborator Author

Not sure it's possible to defer it. Spoolbuddy is getting traction and the current tag assignment has a duplication issue and does not track the correct NFC block. Later changes will have a much broader impact.

@maziggy

maziggy commented May 3, 2026

Copy link
Copy Markdown
Owner

Talking to each other helps ;)

@Keybored02

Copy link
Copy Markdown
Collaborator Author

Will do.

@netscout2001

Copy link
Copy Markdown
Contributor

Hey, thanks a lot for taking the time to put this together — I really appreciate the effort! 🙏

That said, I don't want to pull this into my current PR at this point. It can be revisited and implemented once I'm done with the Spoolman integration on my side — I'd rather not introduce a second UUID in there right now.

I only had a quick look, so this is a fly-by review, but from what I can see the test coverage isn't complete yet — a few tests are in there, but not enough to fully cover the changes. On top of that, this is more of a new feature than only a bug fix.

Let's revisit this later once Spoolman is wrapped up. Thanks again for contributing! 🚀

@Keybored02

Copy link
Copy Markdown
Collaborator Author

Thanks for taking the time to review this.

This is not a DB feature but rather a fix for an issue in Spoolbuddy. A Bambulab spool has two tags, each with one unique tag_uid, but both sharing the same tray_uuid values (the correct identifier). The NFC currently reads and saves only tag_uid , which means that a spool will be duplicated into two entities based on the side on which is scanned. This effectively nullifies the usefulness of SB, and creates a DB state that is complex to reconcile in the future.

If you think that covering the full behavior is excessive (2 tags and 1 tray IDs per spool), at least add the switch to tray_uuid and the hw config for that.

Given that the project is getting quite a bit more users recently, I do not see how this can be postponed. I can extendTesting coverage.

@maziggy

maziggy commented May 3, 2026

Copy link
Copy Markdown
Owner

Unfortunately we have to postpone it until PR #1114 is finished. The PR is too complex and I would like to get it finished.

I also don't see any pressure with the duplicate tags. Don't experienced any issues with it unti now and also don't received any issues which are related.

@maziggy

maziggy commented May 3, 2026

Copy link
Copy Markdown
Owner

BTW: we are talking about BL spools - third party spools don't have the issue. So we have a nice workaround until it's fixed: don't weigh your BL spools, just put them into the AMS.

@Keybored02

Keybored02 commented May 3, 2026

Copy link
Copy Markdown
Collaborator Author

Don't experienced any issues with it unti now and also don't received any issues which are related.

I constantly run into this issue. The lack of reporting would probably be for the fact that it's rather hard to catch.

don't weigh your BL spools, just put them into the AMS.

That's not how people are using it though.

Anyway, will wait.

@maziggy

maziggy commented May 3, 2026

Copy link
Copy Markdown
Owner

That's not how people are using it though.

Sure, it's a workaround until the fix lands.

@maziggy

maziggy commented May 8, 2026

Copy link
Copy Markdown
Owner

I've just merged the large unified inventory PR. Now it's the perfect time to merge your changes.

@maziggy

maziggy commented May 8, 2026

Copy link
Copy Markdown
Owner

Lemme check....

@Keybored02

Copy link
Copy Markdown
Collaborator Author

I'll fix the merging issues, add test coverage, and test the while thing again. Will take a while.

@maziggy

maziggy commented May 8, 2026

Copy link
Copy Markdown
Owner

Wait....I'm nearly finished with resolving conflicts.

@maziggy maziggy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three things worth changing before merge plus one nit:

  1. tag_uid_2 length should be VARCHAR(32), not VARCHAR(16).

PR #1241 widened tag_uid from String(16) to String(32) to support the full Bambu tray UUID width. Adding tag_uid_2 as String(16) reintroduces the old limit on a brand-new column, so the secondary slot can't hold the same kinds of UIDs the primary slot now accepts. I bumped this to String(32) (and the migration ALTER TABLE to VARCHAR(32)) during the merge — please confirm that's what you wanted.

  1. InventorySpool.tag_uid_2 should be optional, not required.

Making it tag_uid_2: string | null (required) breaks every existing literal that constructs an InventorySpool shape — tsc -b flagged three on dev that the PR didn't touch:

  • frontend/src/components/ForecastPanel.tsx:1189 (bulkCreateSpools payload from "received" shopping-list items)
  • frontend/src/pages/spoolbuddy/SpoolBuddyDashboard.tsx — the setJustLinkedSpool literal in the Spoolman link branch
  • frontend/src/pages/spoolbuddy/SpoolBuddyDashboard.tsx — the createSpoolmanInventorySpool payload in the Spoolman quick-add branch

I added tag_uid_2: null in those three spots so the build passes, but the cleaner long-term fix is tag_uid_2?: string | null on the InventorySpool interface — matches how every other additive column in this codebase has been introduced and avoids the next dev who adds an inventory literal silently breaking the build.

  1. Spoolman backend has no tag_uid_2 column.

The dual-UID feature is local-DB only — Spoolman's REST API doesn't expose a second tag field, and _map_spoolman_spool won't have anywhere to read one from. So under
spoolman_enabled=true, the secondary UID column is unreachable: setting it via the form persists only locally (and only in local mode), and no Spoolman spool will ever match against it. That's fine as a scoping decision, but worth saying so explicitly in the PR description so users on Spoolman don't expect dual-reader matching to work.

  1. Nit: setShowLinkModal(false) on the success path of handleLinkTagToSpool is redundant with the existing finally { setShowLinkModal(false) }. Removed during the merge.

@netscout2001

Copy link
Copy Markdown
Contributor

For 3. it is possible to add a tag2 field as extra field to spoolman.
So it is 100% the same as for local inventory.

@Keybored02

Copy link
Copy Markdown
Collaborator Author
  1. Confirm, it's fine

the cleaner long-term fix is tag_uid_2?: string | null on the InventorySpool interface

  1. Agree
  2. As @netscout2001 mentioned, it can be added as an extra field.
  3. Fine.

@maziggy

maziggy commented May 11, 2026

Copy link
Copy Markdown
Owner

Question is, if this PR is still good after merging the huge "Unified inventory" code.

@Keybored02

Keybored02 commented May 12, 2026

Copy link
Copy Markdown
Collaborator Author

I've not run into any particular issues with my flow, but I've not tested extensively on Spoolman. I'm also unclear if you still need me to add anything before a review? Seems like you've already fixed the remaining points.

@maziggy

maziggy commented Jun 19, 2026

Copy link
Copy Markdown
Owner

Please rebase to resolve conflicts.

@tooldforgames

Copy link
Copy Markdown

@Keybored02 . i think you are making this more complicated than it needs to be (speaking for bambu labs spools only) the Only key you need is tray_uuid key 9 if this is saved in tag in spoolman then the scale and the AMS will both see the same record, tag_uid nor tag_uid2 is really needed for bambu spools, if you must have one to display on the scale then use the first 8 char or last 8 char of key 9 this is the same both sides of the spool ID.
I have added some of the changes keybored02 made to add key 9 and i dont have the knowledge to save it so spoolman tag, i believe this uses tag_uid and it cant hold the full key 9. this means the record wont save with the full key, but when the scale scans key 9 and you already have a ams record the scale will see it.

@maziggy the scale is basically useless as it stands for bambu spools.
put spool in ams and it creates a record
put spool on scale, it prompts to create a new record (blank) you cant select the ams record as it has a rag id in spoolman so is not shown to select so the record is created and cant be seen by the ams.
put the spool on the scale again and the scale has a 50-50 of being a new record (second side tag) or pull the other blank record.

The key to all this is key 9, sorry for the pun there, as i say i have edited some of the code and have the scale seeing the ams record and updating it, but cant create records :(

regards
tooldforgames

Sorry if its not allowed to post these sort of comments here

@maziggy

maziggy commented Jun 30, 2026

Copy link
Copy Markdown
Owner

@maziggy the scale is basically useless as it stands for bambu spools.
put spool in ams and it creates a record
put spool on scale, it prompts to create a new record (blank) you cant select the ams record as it has a rag id in spoolman so is not shown to select so the record is created and cant be seen by the ams.
put the spool on the scale again and the scale has a 50-50 of being a new record (second side tag) or pull the other blank record.

Use the latest version and disable auto-create in settings.

@tooldforgames

tooldforgames commented Jun 30, 2026 via email

Copy link
Copy Markdown

@Keybored02

Copy link
Copy Markdown
Collaborator Author

@tooldforgames We need to keep tag_UID support both for non-BL spools and for backwards compatibility with inventory records using them. I'm working a migration path for the older BL spools.

@apoapoapo

Copy link
Copy Markdown

@maziggy the scale is basically useless as it stands for bambu spools.
put spool in ams and it creates a record
put spool on scale, it prompts to create a new record (blank) you cant select the ams record as it has a rag id in spoolman so is not shown to select so the record is created and cant be seen by the ams.
put the spool on the scale again and the scale has a 50-50 of being a new record (second side tag) or pull the other blank record.

Use the latest version and disable auto-create in settings.

i tested that in that issue here but it was closed:
#1810

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants