Add nfc_card_id field (bytes 3-6 as decimal) for standard NFC reader compatibility

- TagInfo now includes nfc_card_id: the 10-digit decimal ID standard NFC readers display
- Calculated from bytes 3-6 of the 7-byte UID as big-endian uint32
- Example: UID 042B603A9A4080 -> nfc_card_id 983187584
- Updated standalone test to display nfc_card_id
- Version bump to 1.4.0
This commit is contained in:
2026-02-21 18:59:01 +11:00
parent 0da6f54889
commit 203ea48c21

View File

@@ -6,6 +6,11 @@ For Moonlight Drive-In Video Player System
Communicates with LEGO Dimensions USB portal (PS3/PS4/Wii U versions)
to detect character and vehicle disc placement/removal events.
v1.4.0 Changes:
- Added nfc_card_id field: decimal ID matching standard NFC readers
- Calculated from bytes 3-6 of UID as big-endian uint32
- Example: UID 042B603A9A4080 -> nfc_card_id 983187584
v1.3.0 Changes:
- Removed default LED blink on tag insert (callbacks now control LEDs)
- Added software_flash() method for reliable flashing via solid color loop
@@ -81,7 +86,7 @@ VENDOR_ID = 0x0e6f
PRODUCT_ID = 0x0241
# Module version
__version__ = "1.3.0"
__version__ = "1.4.0"
def get_usb_backend():
@@ -148,16 +153,28 @@ class TagInfo:
pad: Pad
event: TagEvent
uid_hex: str = ""
legacy_key: int = 0 # Integer key for tag_colors.json lookup
nfc_card_id: int = 0 # Standard NFC card ID (bytes 3-6 as decimal)
legacy_key: int = 0 # Legacy key (first 4 bytes, big-endian)
character_id: Optional[int] = None
character_name: Optional[str] = None
is_vehicle: bool = False
def __post_init__(self):
self.uid_hex = self.uid.hex().upper()
# Calculate legacy key (32-bit int from first 4 bytes, big-endian)
if len(self.uid) >= 4:
self.legacy_key = int.from_bytes(self.uid[:4], 'big')
# Calculate NFC card ID (bytes 3-6 as big-endian uint32)
# This matches what standard NFC readers display (e.g., 983187584)
if len(self.uid) >= 7:
self.nfc_card_id = int.from_bytes(self.uid[3:7], 'big')
@property
def nfc_card_id_str(self) -> str:
"""Return NFC card ID as zero-padded 10-digit string."""
return f"{self.nfc_card_id:010d}"
class LegoDimensionsReader:
@@ -167,13 +184,14 @@ class LegoDimensionsReader:
Provides event-driven tag detection with callbacks for integration
with the Moonlight Drive-In video player system.
v1.4.0: TagInfo now includes nfc_card_id matching standard NFC readers.
v1.3.0: No default LED behavior on tag insert/remove.
Callbacks are fully responsible for LED control.
Usage:
reader = LegoDimensionsReader()
reader.on_tag_insert = lambda tag: print(f"Tag placed: {tag.uid_hex}")
reader.on_tag_remove = lambda tag: print(f"Tag removed: {tag.uid_hex}")
reader.on_tag_insert = lambda tag: print(f"Tag placed: {tag.nfc_card_id}")
reader.on_tag_remove = lambda tag: print(f"Tag removed: {tag.nfc_card_id}")
reader.start()
"""
@@ -629,7 +647,7 @@ class LegoDimensionsReader:
event = TagEvent.INSERTED if action == 0 else TagEvent.REMOVED
tag_info = TagInfo(uid=uid, pad=pad, event=event)
# v1.3.0: NO default LED behavior - callbacks control LEDs
# v1.3.0+: NO default LED behavior - callbacks control LEDs
if event == TagEvent.INSERTED:
self._active_tags[pad_num] = tag_info
if self.on_tag_insert:
@@ -797,7 +815,7 @@ if __name__ == "__main__":
print(f"\n{'='*50}")
print(f"[+] TAG PLACED on {tag.pad.name} pad")
print(f" UID: {tag.uid_hex}")
print(f" Legacy Key: {tag.legacy_key}")
print(f" NFC Card ID: {tag.nfc_card_id} ({tag.nfc_card_id_str})")
print(f" Password: {generate_password(tag.uid).hex().upper()}")
print(f"{'='*50}")
@@ -816,8 +834,8 @@ if __name__ == "__main__":
print(f"\nLEGO Dimensions Portal Reader v{__version__}")
print(f"Platform: {platform.system()}")
print("="*50)
print("NOTE: v1.3.0 - No default LED blink on tag insert")
print(" Callbacks control all LED behavior")
print("v1.4.0: Now shows NFC Card ID (decimal) for compatibility")
print(" with standard NFC readers and mapping files")
print("="*50)
reader = LegoDimensionsReader()
@@ -841,4 +859,4 @@ if __name__ == "__main__":
print(f"\nConnection failed: {e}")
finally:
reader.disconnect()
print("Goodbye!")
print("Goodbye!")