Prox Generic Credential Formats
PROX_GENERIC credentials are 6 bytes (48 bits) encoded in Little Endian byte order. This format works simply and flexibly by assigning the raw byte stream the credential transmits to the Last Lock device. This allows a wide range of credential formats to be supported, with encoding and decoding logic left to the caller.
Header Table
Not all PACS providers expose the header directly, so it is listed here for reference.
| Bit Length | Header (Binary) | Header Bits |
|---|---|---|
| 26-bit | 0000 0010 0000 0000 01 | 18 |
| 27-bit | 0000 0010 0000 0000 1 | 17 |
| 28-bit | 0000 0010 0000 0001 | 16 |
| 29-bit | 0000 0010 0000 001 | 15 |
| 30-bit | 0000 0010 0000 01 | 14 |
| 31-bit | 0000 0010 0000 1 | 13 |
| 32-bit | 0000 0010 0001 | 12 |
| 33-bit | 0000 0010 001 | 11 |
| 34-bit | 0000 0010 01 | 10 |
| 35-bit | 0000 0010 1 | 9 |
| 36-bit | 0000 0011 | 8 |
| 37-bit | 0000 000 | 7 |
PROX 10301 Example (26-bit)
This is intended only as an example of how to encode a credential, following the header table provided above. Your mileage may vary depending on the specific credential format you are using. Refer to the documentation provided by the issuer of your credentials for the correct byte structure.
This specific PROX 10301 is 26 bits: [even_parity:1][facility:8][card_number:16][odd_parity:1]
Example: Facility=123, Card=45678
Step 1: Card data (26 bits)
Parity | Facility (123) | Card Number (45678) | Parity
1 | 01111011 | 1011001001101110 | 1
= 10111101110110010011011101
Even parity: count 1s in (facility + top 4 bits of card) = 9 → parity = 1
Odd parity: count 1s in (bottom 12 bits of card) = 6 → parity = 1
Step 2: Add 18-bit header (for 26-bit format)
Header (18 bits) | Card Data (26 bits)
000000100000000001 | 10111101110110010011011101
= 00000010000000000110111101110110010011011101 (44 bits)
Step 3: Pad to 48 bits (add 4 zero bits at MSB)
0000 00000010000000000110111101110110010011011101
= 0x002006F764DD (big endian)
Step 4: Convert to Little Endian bytes
Big Endian: 00 20 06 F7 64 DD
Little Endian: DD 64 F7 06 20 00
Final credential data: DD64F7062000
def encode_h10301(facility_code: int, card_number: int) -> bytes:
"""Encode PROX 10301 as PROX_GENERIC (6 bytes, Little Endian)."""
data_24 = (facility_code << 16) | card_number
# Calculate parity
upper_12 = (facility_code << 4) | (card_number >> 12)
even_parity = bin(upper_12).count('1') % 2
lower_12 = card_number & 0xFFF
odd_parity = 1 - (bin(lower_12).count('1') % 2)
# Assemble 26-bit card data
card_26 = (even_parity << 25) | (data_24 << 1) | odd_parity
# Add 18-bit header (26-bit format), giving 44 bits total
header_26bit = (1 << 11) | 1 # 0b000000100000000001 = 2049
value_44 = (header_26bit << 26) | card_26
return value_44.to_bytes(6, byteorder='little')
# Example: facility=123, card=45678 -> DD64F7062000
credential_data = encode_h10301(123, 45678)
Assign to a device:
credential = org_pb2.Credential(
credential_type=org_pb2.PROX_GENERIC,
data=encode_h10301(123, 45678) # DD64F7062000
)
org.Assign(org_pb2.AssignmentsRequest(
assignments={14: org_pb2.Credentials(credentials=[credential])}
))