Initializare dupa curatare folder

This commit is contained in:
2026-10-05 11:46:46 +03:00
commit 48e800adc1
39 changed files with 6303 additions and 0 deletions
+108
View File
@@ -0,0 +1,108 @@
"""RDM6300 wire format: type + id + checksum, 12 hex nibbles per frame.
The checksum is the XOR of the type byte *and* the four id bytes. Getting this
wrong (e.g. XOR-ing only the id) makes every card read fail its checksum, so
the exact bytes are pinned here.
"""
import struct
import pytest
from rdm_card_reader.card import CardData
START = 0x02
END = 0x03
def encode_frame(value, card_type=0x0F):
"""Encode a card as the 12 nibbles the RDM6300 emits between STX and ETX."""
id_bytes = struct.pack(">I", value)
checksum = card_type
for byte in id_bytes:
checksum ^= byte
frame = bytes([card_type]) + id_bytes + bytes([checksum])
encoded = frame.hex().upper().encode("ascii")
assert len(encoded) == 12
return encoded
def encode_stream(value, card_type=0x0F):
return bytes([START]) + encode_frame(value, card_type) + bytes([END])
def decode_frame(frame):
"""Reference decoder mirroring rdm6300.BaseReader._parse_fragment."""
nibbles = [int(ch, 16) for ch in frame.decode("ascii")]
def to_int(chunk):
out = 0
for item in chunk:
out = (out << 4) | item
return out
calculated = 0
for i in range(0, 10, 2):
calculated ^= (nibbles[i] << 4) | nibbles[i + 1]
received = to_int(nibbles[10:12])
return CardData(
value=to_int(nibbles[2:10]),
checksum=received,
is_valid=received == calculated,
type=to_int(nibbles[0:2]),
)
@pytest.mark.parametrize(
"value,expected",
[
(0x00C4A0B5, b"0F00C4A0B5DE"),
(0x1A2B3C4D, b"0F1A2B3C4D4F"),
],
)
def test_encoded_frame_bytes_are_stable(value, expected):
assert encode_frame(value) == expected
def test_frame_is_twelve_nibbles():
assert len(encode_frame(0x00C4A0B5)) == 12
def test_checksum_covers_type_byte_not_only_id():
"""Same id with a different type byte must change the checksum."""
assert encode_frame(0x00C4A0B5, 0x0F) != encode_frame(0x00C4A0B5, 0x10)
def test_round_trip_yields_valid_card():
card = decode_frame(encode_frame(0x00C4A0B5))
assert card.value == 0x00C4A0B5
assert card.type == 0x0F
assert card.checksum == 0xDE
assert card.is_valid is True
def test_round_trip_of_second_sample():
card = decode_frame(encode_frame(0x1A2B3C4D))
assert card.value == 0x1A2B3C4D
assert card.is_valid is True
def test_corrupted_checksum_is_invalid():
frame = bytearray(encode_frame(0x00C4A0B5))
frame[-1] = ord("0")
assert decode_frame(bytes(frame)).is_valid is False
def test_frame_with_wrong_nibble_count_is_rejected():
"""A 14 nibble frame leaves 2 nibbles buffered in the real reader."""
assert len(encode_frame(0x00C4A0B5)) == 12
fourteen = b"0F00C4A0B5DE00"
assert len(fourteen) == 14
def test_stream_wrapper_uses_stx_and_etx():
stream = encode_stream(0x00C4A0B5)
assert stream[0] == START
assert stream[-1] == END
assert stream[1:-1] == encode_frame(0x00C4A0B5)