feat: set_uid() with validation and random generation for 15693 tags
Tag15693.set_uid() now: - Accepts None (or no args) to generate a random valid UID with the correct IC-specific prefix (E0 + mfg + IC type) - Validates length (must be 8 bytes) - Warns on prefix mismatch (wrong IC type for product-specific tags) - Warns on non-NXP manufacturer code - Warns on missing E0 prefix
This commit is contained in:
@@ -128,6 +128,46 @@ class Tag15693(Transponder):
|
||||
random_bytes = os.urandom(8 - len(prefix))
|
||||
return prefix + random_bytes
|
||||
|
||||
def set_uid(self, uid: bytes | str | None = None) -> None:
|
||||
"""Change the tag UID. Call sync() to push to firmware.
|
||||
|
||||
uid=None generates a random valid UID with the correct IC prefix.
|
||||
Warns if the UID prefix doesn't match the expected IC type.
|
||||
"""
|
||||
import warnings
|
||||
if uid is None:
|
||||
self._uid = self._generate_uid()
|
||||
self._uid_dirty = True
|
||||
return
|
||||
uid = self._parse_uid(uid)
|
||||
if len(uid) != 8:
|
||||
raise ValueError(f"UID must be 8 bytes, got {len(uid)}")
|
||||
prefix = self._uid_prefix
|
||||
if len(prefix) > 2 and uid[:len(prefix)] != prefix:
|
||||
expected = prefix.hex().upper()
|
||||
actual = uid[:len(prefix)].hex().upper()
|
||||
cls_name = type(self).__name__
|
||||
warnings.warn(
|
||||
f"{cls_name}: UID prefix {actual} doesn't match expected {expected}. "
|
||||
f"Phones/readers may not identify the IC type correctly. "
|
||||
f"Use set_uid() with no args for a valid random UID.",
|
||||
stacklevel=2,
|
||||
)
|
||||
elif uid[:2] != b"\xE0\x04" and uid[:1] == b"\xE0":
|
||||
warnings.warn(
|
||||
f"UID manufacturer code {uid[1]:02X} is not NXP (04). "
|
||||
f"Phones may not recognize this as an NXP tag.",
|
||||
stacklevel=2,
|
||||
)
|
||||
elif uid[:1] != b"\xE0":
|
||||
warnings.warn(
|
||||
f"UID must start with E0 (ISO 15693 IC manufacturer prefix). "
|
||||
f"Got {uid[0]:02X}. This UID will not be recognized by readers.",
|
||||
stacklevel=2,
|
||||
)
|
||||
self._uid = uid
|
||||
self._uid_dirty = True
|
||||
|
||||
def decode_trace(self, direction: int, payload: bytes) -> str | None:
|
||||
return decode_15693(direction, payload)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user