reader-integration-kit 1.4.2__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. reader_integration_kit/__init__.py +12 -0
  2. reader_integration_kit/enum/__init__.py +28 -0
  3. reader_integration_kit/enum/beep_duration.py +12 -0
  4. reader_integration_kit/enum/beep_volume.py +15 -0
  5. reader_integration_kit/enum/ble_data_type.py +12 -0
  6. reader_integration_kit/enum/blob_type.py +27 -0
  7. reader_integration_kit/enum/checkpoint_type.py +13 -0
  8. reader_integration_kit/enum/data_conversion_type.py +12 -0
  9. reader_integration_kit/enum/field_definition_type.py +14 -0
  10. reader_integration_kit/enum/led_color.py +15 -0
  11. reader_integration_kit/enum/protocol_type.py +14 -0
  12. reader_integration_kit/enum/proximity_card_type.py +166 -0
  13. reader_integration_kit/enum/reader_module_id.py +13 -0
  14. reader_integration_kit/enum/reader_module_state.py +12 -0
  15. reader_integration_kit/enum/serial_port_baud_rate.py +15 -0
  16. reader_integration_kit/enum/serial_port_data_bits.py +10 -0
  17. reader_integration_kit/enum/serial_port_flow_control.py +11 -0
  18. reader_integration_kit/enum/serial_port_parity.py +10 -0
  19. reader_integration_kit/enum/serial_port_stop_bits.py +9 -0
  20. reader_integration_kit/enum/transparent_mode_state.py +11 -0
  21. reader_integration_kit/enum/transparent_mode_status.py +11 -0
  22. reader_integration_kit/errors/__init__.py +4 -0
  23. reader_integration_kit/errors/reader_exception.py +58 -0
  24. reader_integration_kit/facade/__init__.py +882 -0
  25. reader_integration_kit/lib/ReaderIntegrationKit.dll +0 -0
  26. reader_integration_kit/structures/__init__.py +36 -0
  27. reader_integration_kit/structures/blob_header.py +54 -0
  28. reader_integration_kit/structures/bluetooth_firmware_version.py +35 -0
  29. reader_integration_kit/structures/card_data.py +77 -0
  30. reader_integration_kit/structures/card_type_info.py +51 -0
  31. reader_integration_kit/structures/device_id.py +12 -0
  32. reader_integration_kit/structures/extended_configuration.py +32 -0
  33. reader_integration_kit/structures/felica_sam_firmware_version.py +38 -0
  34. reader_integration_kit/structures/field_entry.py +120 -0
  35. reader_integration_kit/structures/field_separator_data_header.py +83 -0
  36. reader_integration_kit/structures/hash_data.py +55 -0
  37. reader_integration_kit/structures/hid_se_sam_firmware_version.py +38 -0
  38. reader_integration_kit/structures/led_configuration.py +13 -0
  39. reader_integration_kit/structures/library_info.py +74 -0
  40. reader_integration_kit/structures/luid_response_information.py +44 -0
  41. reader_integration_kit/structures/microcontroller_firmware_version.py +38 -0
  42. reader_integration_kit/structures/nxp_sam_firmware_version.py +38 -0
  43. reader_integration_kit/structures/reader_configuration.py +171 -0
  44. reader_integration_kit/structures/reader_data.py +49 -0
  45. reader_integration_kit/structures/reader_definition.py +14 -0
  46. reader_integration_kit/structures/reader_metadata_struct.py +195 -0
  47. reader_integration_kit/structures/rik_result.py +71 -0
  48. reader_integration_kit/structures/separator_character.py +44 -0
  49. reader_integration_kit/structures/separator_entry.py +73 -0
  50. reader_integration_kit/structures/serial_port_settings.py +45 -0
  51. reader_integration_kit/structures/smart_card_configuration.py +34 -0
  52. reader_integration_kit-1.4.2.dist-info/METADATA +139 -0
  53. reader_integration_kit-1.4.2.dist-info/RECORD +56 -0
  54. reader_integration_kit-1.4.2.dist-info/WHEEL +5 -0
  55. reader_integration_kit-1.4.2.dist-info/licenses/rfIDEAS_EULA.txt +281 -0
  56. reader_integration_kit-1.4.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,36 @@
1
+ from reader_integration_kit.structures.device_id import DeviceId
2
+ from reader_integration_kit.structures.reader_definition import ReaderDefinition
3
+ from reader_integration_kit.structures.rik_result import RikResult
4
+ from reader_integration_kit.structures.serial_port_settings import SerialPortSettings
5
+ from reader_integration_kit.structures.reader_metadata_struct import ReaderMetadataStruct
6
+ from reader_integration_kit.structures.microcontroller_firmware_version import \
7
+ MicrocontrollerFirmwareVersion
8
+ from reader_integration_kit.structures.bluetooth_firmware_version import BluetoothFirmwareVersion
9
+ from reader_integration_kit.structures.hid_se_sam_firmware_version import HidSeSamFirmwareVersion
10
+ from reader_integration_kit.structures.nxp_sam_firmware_version import NxpSamFirmwareVersion
11
+ from reader_integration_kit.structures.felica_sam_firmware_version import FelicaSamFirmwareVersion
12
+ from reader_integration_kit.structures.library_info import LibraryInfo
13
+ from reader_integration_kit.structures.card_data import CardData
14
+ from reader_integration_kit.structures.led_configuration import LedConfiguration
15
+ from reader_integration_kit.structures.reader_configuration import ReaderConfigurationStruct
16
+ from reader_integration_kit.structures.reader_data import ReaderData
17
+ from reader_integration_kit.structures.field_entry import FieldEntry
18
+ from reader_integration_kit.structures.separator_entry import SeparatorEntry
19
+ from reader_integration_kit.structures.field_separator_data_header import FieldSeparatorDataHeader
20
+ from reader_integration_kit.structures.separator_character import SeparatorCharacter
21
+ from reader_integration_kit.structures.extended_configuration import ExtendedConfiguration
22
+ from reader_integration_kit.structures.hash_data import HashData
23
+ from reader_integration_kit.structures.luid_response_information import LuidResponseInformation
24
+ from reader_integration_kit.structures.card_type_info import CardTypeInfo, SupportedCardTypesResult
25
+ from reader_integration_kit.structures.blob_header import BlobHeader
26
+ from reader_integration_kit.structures.smart_card_configuration import SmartCardConfigurationStruct
27
+
28
+ __all__ = [
29
+ 'DeviceId', 'ReaderDefinition', 'RikResult', 'SerialPortSettings',
30
+ 'ReaderMetadataStruct', 'MicrocontrollerFirmwareVersion', 'BluetoothFirmwareVersion',
31
+ 'HidSeSamFirmwareVersion', 'NxpSamFirmwareVersion', 'FelicaSamFirmwareVersion', 'LibraryInfo',
32
+ 'CardData', 'LedConfiguration', 'ReaderConfigurationStruct', 'ReaderData', 'FieldEntry',
33
+ 'LuidResponseInformation', 'SeparatorEntry', 'FieldSeparatorDataHeader', 'SeparatorCharacter',
34
+ 'ExtendedConfiguration', 'HashData',
35
+ 'CardData', 'CardTypeInfo', 'SupportedCardTypesResult', 'BlobHeader', 'SmartCardConfigurationStruct'
36
+ ]
@@ -0,0 +1,54 @@
1
+ import struct
2
+ from ctypes import Structure, c_uint8, c_uint16
3
+ from typing import Any
4
+
5
+ from reader_integration_kit.enum import BlobType
6
+
7
+ class BlobHeader(Structure):
8
+ _pack_ = 1
9
+ _fields_ = [
10
+ ("Type", c_uint8),
11
+ ("ID", c_uint8),
12
+ ("DataLength", c_uint16),
13
+ ("BSV", c_uint8),
14
+ ]
15
+
16
+ def __init__(self, *args: Any, **kw: Any):
17
+ super().__init__()
18
+ self.Type = kw.get("Type", args[0] if len(args) > 0 else BlobType.LEGACY_KEY.value)
19
+ self.ID = kw.get("ID", args[1] if len(args) > 1 else 0)
20
+ self.DataLength = kw.get("DataLength", args[2] if len(args) > 2 else 0)
21
+ self.BSV = kw.get("BSV", args[3] if len(args) > 3 else 0)
22
+
23
+ def __str__(self):
24
+ return (f"Blob type: {BlobType(self.Type).name}\n" +
25
+ f"ID: {self.ID}\n" +
26
+ f"Data length: {self.DataLength}\n" +
27
+ f"BSV: {self.BSV}\n"
28
+ )
29
+
30
+ def __repr__(self):
31
+ return self.__str__()
32
+
33
+ def __eq__(self, other):
34
+ return self.Type == other.Type and self.ID == other.ID and self.DataLength == other.DataLength and self.BSV == other.BSV
35
+
36
+ def __ne__(self, other):
37
+ return not self.__eq__(other)
38
+
39
+ def to_dict(self):
40
+ return {
41
+ "Type": BlobType(self.Type).name,
42
+ "ID": self.ID,
43
+ "DataLength": self.DataLength,
44
+ "BSV": self.BSV,
45
+ }
46
+
47
+ def to_bytes(self):
48
+ # Pack as: Type(u8), ID(u8), DataLength(u16 LE), BSV(u8) = 5 bytes
49
+ return struct.pack('<BBHB', self.Type, self.ID, self.DataLength, self.BSV)
50
+
51
+ @classmethod
52
+ def from_bytes(cls, byte_array):
53
+ type_, id_, data_length, bsv = struct.unpack('<BBHB', bytes(byte_array[:5]))
54
+ return cls(Type=type_, ID=id_, DataLength=data_length, BSV=bsv)
@@ -0,0 +1,35 @@
1
+ from ctypes import Structure, c_uint32, c_uint8, c_int32
2
+ from typing import Any
3
+
4
+
5
+ class BluetoothFirmwareVersion(Structure):
6
+ _pack_ = 1 # Ensure no padding between fields for native compatibility
7
+ _fields_ = [
8
+ ("Major", c_uint32),
9
+ ("Minor", c_uint32),
10
+ ("Build", c_uint32),
11
+ ("MicrocontrollerType", c_int32), # enum class in C++ uses int (4 bytes)
12
+ ("ModuleType", c_int32), # enum class in C++ uses int (4 bytes)
13
+ ]
14
+
15
+ def __init__(self, *args: Any, **kw: Any):
16
+ super().__init__()
17
+ self.ModuleType = kw.get("ModuleType", 0)
18
+ self.MicrocontrollerType = kw.get("MicrocontrollerType", 0)
19
+ self.Build = kw.get("Build", 0)
20
+ self.Minor = kw.get("Minor", 0)
21
+ self.Major = kw.get("Major", 0)
22
+
23
+ def to_dict(self):
24
+ """Convert to dictionary."""
25
+ return {
26
+ "Major": self.Major,
27
+ "Minor": self.Minor,
28
+ "Build": self.Build,
29
+ "MicrocontrollerType": self.MicrocontrollerType,
30
+ "ModuleType": self.ModuleType,
31
+ }
32
+
33
+ def __str__(self):
34
+ return f"{self.Major}.{self.Minor}.{self.Build}"
35
+
@@ -0,0 +1,77 @@
1
+ """CardData structure for the Reader Integration Kit."""
2
+
3
+ from typing import List
4
+
5
+
6
+ class CardData:
7
+ """
8
+ Represents card data read from an RFID reader.
9
+
10
+ This structure contains the raw card data bytes and associated metadata
11
+ such as the bit count of the data read.
12
+ """
13
+
14
+ def __init__(self):
15
+ """Initialize a new CardData instance with empty data."""
16
+ self.data = [0] * 32 # 32-byte array for card data
17
+ self._bit_count = 0
18
+
19
+ @property
20
+ def bit_count(self) -> int:
21
+ """Get the bit count of the card data."""
22
+ return self._bit_count
23
+
24
+ @bit_count.setter
25
+ def bit_count(self, value: int):
26
+ """Set the bit count of the card data."""
27
+ self._bit_count = value
28
+
29
+ def is_empty(self) -> bool:
30
+ """
31
+ Check if the card data is empty.
32
+
33
+ Returns:
34
+ True if the bit count is zero and the data is empty or all bytes are zero, False otherwise.
35
+ """
36
+ if self._bit_count != 0:
37
+ return False
38
+ if not self.data:
39
+ return True
40
+ return all(byte == 0 for byte in self.data)
41
+
42
+ def as_bytes(self) -> bytes:
43
+ """
44
+ Get the card data as a bytes object.
45
+
46
+ Returns:
47
+ The card data as a bytes object.
48
+ """
49
+ return bytes(self.data)
50
+
51
+ def as_list(self) -> List[int]:
52
+ """
53
+ Get the card data as a list of integers.
54
+
55
+ Returns:
56
+ The card data as a list of integers (0-255).
57
+ """
58
+ return list(self.data)
59
+
60
+ def as_hex_string(self) -> str:
61
+ """
62
+ Get the card data as a hexadecimal string.
63
+
64
+ Returns:
65
+ The card data as a hex string (e.g., "12 34 56 78 ...").
66
+ """
67
+ return ' '.join(f'{byte:02X}' for byte in self.data)
68
+
69
+ def __repr__(self) -> str:
70
+ """Return a string representation of the CardData."""
71
+ valid = "Empty" if self.is_empty() else "Not Empty"
72
+ return f"CardData(bit_count={self.bit_count}, {valid}, data={self.as_hex_string()[:24]}...)"
73
+
74
+ def __str__(self) -> str:
75
+ """Return a user-friendly string representation."""
76
+ return self.__repr__()
77
+
@@ -0,0 +1,51 @@
1
+ """
2
+ CardTypeInfo ctypes structure matching the C ABI CardTypeInfo struct from RikCommon.
3
+ """
4
+ import ctypes
5
+
6
+
7
+ class CardTypeInfo(ctypes.Structure):
8
+ """ABI-safe structure describing a single card type.
9
+
10
+ Attributes:
11
+ Value: The 16-bit card type value as used by the reader protocol.
12
+ Name: Human-readable display name (e.g., "DESFire CSN (Oyster, NFC 4)").
13
+ EnumName: Enum/identifier name (e.g., "DESFIRE").
14
+ """
15
+ _pack_ = 1
16
+ _fields_ = [
17
+ ("Value", ctypes.c_uint16),
18
+ ("Name", ctypes.c_char * 128),
19
+ ("EnumName", ctypes.c_char * 64),
20
+ ]
21
+
22
+ def to_dict(self) -> dict:
23
+ """Convert to a Python dictionary with decoded strings."""
24
+ return {
25
+ "Value": self.Value,
26
+ "Name": self.Name.decode("utf-8", errors="replace").rstrip("\x00"),
27
+ "EnumName": self.EnumName.decode("utf-8", errors="replace").rstrip("\x00"),
28
+ }
29
+
30
+ def __repr__(self) -> str:
31
+ name = self.Name.decode("utf-8", errors="replace").rstrip("\x00")
32
+ enum_name = self.EnumName.decode("utf-8", errors="replace").rstrip("\x00")
33
+ return f"CardTypeInfo(Value=0x{self.Value:04X}, Name='{name}', EnumName='{enum_name}')"
34
+
35
+
36
+ # Maximum number of supported card types - must match RIK_MAX_SUPPORTED_CARD_TYPES in C header
37
+ RIK_MAX_SUPPORTED_CARD_TYPES = 256
38
+
39
+
40
+ class SupportedCardTypesResult(ctypes.Structure):
41
+ """Fixed-size, ABI-safe result structure for GetSupportedCardTypes.
42
+
43
+ Attributes:
44
+ Count: The number of valid CardTypeInfo entries in the CardTypes array.
45
+ CardTypes: Fixed-size array of CardTypeInfo structs.
46
+ """
47
+ _pack_ = 1
48
+ _fields_ = [
49
+ ("Count", ctypes.c_uint32),
50
+ ("CardTypes", CardTypeInfo * RIK_MAX_SUPPORTED_CARD_TYPES),
51
+ ]
@@ -0,0 +1,12 @@
1
+ from ctypes import Structure, c_ushort, c_char
2
+
3
+
4
+ class DeviceId(Structure):
5
+ _pack_ = 1
6
+ _fields_ = [
7
+ ("VendorId", c_ushort),
8
+ ("ProductId", c_ushort),
9
+ ("UsbPath", c_char * 512),
10
+ ("SerialNumber", c_char * 256),
11
+ ]
12
+
@@ -0,0 +1,32 @@
1
+ import ctypes
2
+ from typing import Any
3
+ from reader_integration_kit.structures.field_separator_data_header import FieldSeparatorDataHeader
4
+ from reader_integration_kit.structures.field_entry import FieldEntry
5
+ from reader_integration_kit.structures.separator_entry import SeparatorEntry
6
+ from reader_integration_kit.structures.reader_data import ReaderData
7
+
8
+ class ExtendedConfiguration(ctypes.Structure):
9
+ _fields_ = [
10
+ ("Header", FieldSeparatorDataHeader),
11
+ ("FieldEntries", FieldEntry * 31),
12
+ ("SeparatorEntries", SeparatorEntry * 31),
13
+ ("AppData", ReaderData)
14
+ ]
15
+
16
+ def __init__(self, *args: Any, **kw: Any):
17
+ super().__init__()
18
+ self.Header = kw.get("Header", args[0] if len(args) > 0 else FieldSeparatorDataHeader())
19
+ self.FieldEntries = kw.get("FieldEntries", args[1] if len(args) > 1 else (FieldEntry * 31)())
20
+ self.SeparatorEntries = kw.get("SeparatorEntries", args[2] if len(args) > 2 else (SeparatorEntry * 31)())
21
+ self.AppData = kw.get("AppData", args[3] if len(args) > 3 else ReaderData())
22
+
23
+ def __eq__(self, other):
24
+ return (
25
+ self.Header == other.Header and
26
+ all(self.FieldEntries[i] == other.FieldEntries[i] for i in range(31)) and
27
+ all(self.SeparatorEntries[i] == other.SeparatorEntries[i] for i in range(31)) and
28
+ self.AppData == other.AppData
29
+ )
30
+
31
+ def __ne__(self, other):
32
+ return not self.__eq__(other)
@@ -0,0 +1,38 @@
1
+ from ctypes import Structure, c_uint8, c_int32
2
+ from typing import Any
3
+
4
+
5
+ class FelicaSamFirmwareVersion(Structure):
6
+ _pack_ = 1 # Ensure no padding between fields for native compatibility
7
+ _fields_ = [
8
+ ("Byte3", c_uint8),
9
+ ("Byte2", c_uint8),
10
+ ("VersionHigh", c_uint8),
11
+ ("VersionLow", c_uint8),
12
+ ("MicrocontrollerType", c_int32), # enum class in C++ uses int (4 bytes)
13
+ ("SamType", c_int32), # enum class in C++ uses int (4 bytes)
14
+ ]
15
+
16
+ def __init__(self, *args: Any, **kw: Any):
17
+ super().__init__()
18
+ self.SamType = kw.get("SamType", 0)
19
+ self.MicrocontrollerType = kw.get("MicrocontrollerType", 0)
20
+ self.VersionLow = kw.get("VersionLow", 0)
21
+ self.VersionHigh = kw.get("VersionHigh", 0)
22
+ self.Byte2 = kw.get("Byte2", 0)
23
+ self.Byte3 = kw.get("Byte3", 0)
24
+
25
+ def to_dict(self):
26
+ """Convert to dictionary."""
27
+ return {
28
+ "Byte3": self.Byte3,
29
+ "Byte2": self.Byte2,
30
+ "VersionHigh": self.VersionHigh,
31
+ "VersionLow": self.VersionLow,
32
+ "MicrocontrollerType": self.MicrocontrollerType,
33
+ "SamType": self.SamType,
34
+ }
35
+
36
+ def __str__(self):
37
+ return f"{self.Byte3}.{self.Byte2}.{self.VersionHigh}.{self.VersionLow}"
38
+
@@ -0,0 +1,120 @@
1
+ from ctypes import Structure, c_uint8
2
+ from typing import Any
3
+
4
+ from reader_integration_kit.enum import DataConversionType
5
+
6
+ class FieldEntry(Structure):
7
+ _fields_ = [
8
+ ("FieldValid", c_uint8),
9
+ ("ConversionType", c_uint8),
10
+ ("FixedFieldOutputLength", c_uint8),
11
+ ("ReverseBits", c_uint8),
12
+ ("ReverseBytes", c_uint8),
13
+ ("FiveBMS", c_uint8),
14
+ ("InvertBits", c_uint8),
15
+ ("ReverseAllBytes", c_uint8),
16
+ ("UseHash", c_uint8),
17
+ ("HashKey", c_uint8),
18
+ ("StartingBitPosition", c_uint8),
19
+ ("BitCountOfField", c_uint8)
20
+ ]
21
+
22
+ def __init__(self, *args: Any, **kw: Any):
23
+ super().__init__()
24
+ self.FieldValid = kw.get("FieldValid", args[0] if len(args) > 0 else 0)
25
+ self.ConversionType = kw.get("ConversionType", args[1] if len(args) > 1 else DataConversionType.DECIMAL.value)
26
+ self.FixedFieldOutputLength = kw.get("FixedFieldOutputLength", args[2] if len(args) > 2 else 0)
27
+ self.ReverseBits = kw.get("ReverseBits", args[3] if len(args) > 3 else 0)
28
+ self.ReverseBytes = kw.get("ReverseBytes", args[4] if len(args) > 4 else 0)
29
+ self.FiveBMS = kw.get("FiveBMS", args[5] if len(args) > 5 else 0)
30
+ self.InvertBits = kw.get("InvertBits", args[6] if len(args) > 6 else 0)
31
+ self.ReverseAllBytes = kw.get("ReverseAllBytes", args[7] if len(args) > 7 else 0)
32
+ self.UseHash = kw.get("UseHash", args[8] if len(args) > 8 else 0)
33
+ self.HashKey = kw.get("HashKey", args[9] if len(args) > 9 else 0)
34
+ self.StartingBitPosition = kw.get("StartingBitPosition", args[10] if len(args) > 10 else 0)
35
+ self.BitCountOfField = kw.get("BitCountOfField", args[11] if len(args) > 11 else 0)
36
+
37
+ def __str__(self):
38
+ return (
39
+ f"FieldValid: {self.FieldValid}\n"
40
+ f"ConversionType: {DataConversionType(self.ConversionType).name}\n"
41
+ f"FixedFieldOutputLength: {self.FixedFieldOutputLength}\n"
42
+ f"ReverseBits: {self.ReverseBits}\n"
43
+ f"ReverseBytes: {self.ReverseBytes}\n"
44
+ f"FiveBMS: {self.FiveBMS}\n"
45
+ f"InvertBits: {self.InvertBits}\n"
46
+ f"ReverseAllBytes: {self.ReverseAllBytes}\n"
47
+ f"UseHash: {self.UseHash}\n"
48
+ f"HashKey: {self.HashKey}\n"
49
+ f"StartingBitPosition: {self.StartingBitPosition}\n"
50
+ f"BitCountOfField: {self.BitCountOfField}\n"
51
+ )
52
+
53
+ def __repr__(self):
54
+ return self.__str__()
55
+
56
+ def __eq__(self, other):
57
+ return (
58
+ self.FieldValid == other.FieldValid
59
+ and self.ConversionType == other.ConversionType
60
+ and self.FixedFieldOutputLength == other.FixedFieldOutputLength
61
+ and self.ReverseBits == other.ReverseBits
62
+ and self.ReverseBytes == other.ReverseBytes
63
+ and self.FiveBMS == other.FiveBMS
64
+ and self.InvertBits == other.InvertBits
65
+ and self.ReverseAllBytes == other.ReverseAllBytes
66
+ and self.UseHash == other.UseHash
67
+ and self.HashKey == other.HashKey
68
+ and self.StartingBitPosition == other.StartingBitPosition
69
+ and self.BitCountOfField == other.BitCountOfField
70
+ )
71
+
72
+ def __ne__(self, other):
73
+ return not self.__eq__(other)
74
+
75
+ def to_dict(self):
76
+ return {
77
+ "FieldValid": self.FieldValid,
78
+ "ConversionType": DataConversionType(self.ConversionType).name,
79
+ "FixedFieldOutputLength": self.FixedFieldOutputLength,
80
+ "ReverseBits": self.ReverseBits,
81
+ "ReverseBytes": self.ReverseBytes,
82
+ "FiveBMS": self.FiveBMS,
83
+ "InvertBits": self.InvertBits,
84
+ "ReverseAllBytes": self.ReverseAllBytes,
85
+ "UseHash": self.UseHash,
86
+ "HashKey": self.HashKey,
87
+ "StartingBitPosition": self.StartingBitPosition,
88
+ "BitCountOfField": self.BitCountOfField
89
+ }
90
+
91
+ @classmethod
92
+ def from_bytes(cls, byte_array):
93
+ return cls(
94
+ FieldValid=byte_array[0],
95
+ ConversionType=byte_array[1],
96
+ FixedFieldOutputLength=byte_array[2],
97
+ ReverseBits=byte_array[3],
98
+ ReverseBytes=byte_array[4],
99
+ FiveBMS=byte_array[5],
100
+ InvertBits=byte_array[6],
101
+ ReverseAllBytes=byte_array[7],
102
+ UseHash=byte_array[8],
103
+ HashKey=byte_array[9],
104
+ StartingBitPosition=byte_array[10],
105
+ BitCountOfField=byte_array[11]
106
+ )
107
+
108
+ def to_bytes(self):
109
+ return bytes([self.FieldValid,
110
+ self.ConversionType,
111
+ self.FixedFieldOutputLength,
112
+ self.ReverseBits,
113
+ self.ReverseBytes,
114
+ self.FiveBMS,
115
+ self.InvertBits,
116
+ self.ReverseAllBytes,
117
+ self.UseHash,
118
+ self.HashKey,
119
+ self.StartingBitPosition,
120
+ self.BitCountOfField])
@@ -0,0 +1,83 @@
1
+ from ctypes import Structure, c_uint8
2
+ from typing import Any
3
+
4
+ class FieldSeparatorDataHeader(Structure):
5
+ _fields_ = [
6
+ ("FieldSeparatorStructureVersion", c_uint8),
7
+ ("HeaderSize", c_uint8),
8
+ ("FieldEntrySize", c_uint8),
9
+ ("FieldEntryCount", c_uint8),
10
+ ("SeparatorEntrySize", c_uint8),
11
+ ("SeparatorEntryCount", c_uint8),
12
+ ("MaxStorageSize", c_uint8)
13
+ ]
14
+
15
+ def __init__(self, *args: Any, **kw: Any):
16
+ super().__init__()
17
+ self.FieldSeparatorStructureVersion = kw.get("FieldSeparatorStructureVersion", args[0] if len(args) > 0 else 1)
18
+ self.HeaderSize = kw.get("HeaderSize", args[1] if len(args) > 1 else 4)
19
+ self.FieldEntrySize = kw.get("FieldEntrySize", args[2] if len(args) > 2 else 4)
20
+ self.FieldEntryCount = kw.get("FieldEntryCount", args[3] if len(args) > 3 else 0)
21
+ self.SeparatorEntrySize = kw.get("SeparatorEntrySize", args[4] if len(args) > 4 else 2)
22
+ self.SeparatorEntryCount = kw.get("SeparatorEntryCount", args[5] if len(args) > 5 else 0)
23
+ self.MaxStorageSize = kw.get("MaxStorageSize", args[6] if len(args) > 6 else 16)
24
+
25
+ def __str__(self):
26
+ return (
27
+ f"FieldSeparatorStructureVersion: {self.FieldSeparatorStructureVersion}\n" +
28
+ f"HeaderSize: {self.HeaderSize}\n"
29
+ f"FieldEntrySize: {self.FieldEntrySize}\n"
30
+ f"FieldEntryCount: {self.FieldEntryCount}\n"
31
+ f"SeparatorEntrySize: {self.SeparatorEntrySize}\n"
32
+ f"SeparatorEntryCount: {self.SeparatorEntryCount}\n"
33
+ f"MaxStorageSize: {self.MaxStorageSize}\n"
34
+ )
35
+
36
+ def __repr__(self):
37
+ return self.__str__()
38
+
39
+ def __eq__(self, other):
40
+ return (
41
+ self.FieldSeparatorStructureVersion == other.FieldSeparatorStructureVersion
42
+ and self.HeaderSize == other.HeaderSize
43
+ and self.FieldEntrySize == other.FieldEntrySize
44
+ and self.FieldEntryCount == other.FieldEntryCount
45
+ and self.SeparatorEntrySize == other.SeparatorEntrySize
46
+ and self.SeparatorEntryCount == other.SeparatorEntryCount
47
+ and self.MaxStorageSize == other.MaxStorageSize
48
+ )
49
+
50
+ def __ne__(self, other):
51
+ return not self.__eq__(other)
52
+
53
+ def to_dict(self):
54
+ return {
55
+ "FieldSeparatorStructureVersion": self.FieldSeparatorStructureVersion,
56
+ "HeaderSize": self.HeaderSize,
57
+ "FieldEntrySize": self.FieldEntrySize,
58
+ "FieldEntryCount": self.FieldEntryCount,
59
+ "SeparatorEntrySize": self.SeparatorEntrySize,
60
+ "SeparatorEntryCount": self.SeparatorEntryCount,
61
+ "MaxStorageSize": self.MaxStorageSize
62
+ }
63
+
64
+ @classmethod
65
+ def from_bytes(cls, byte_array):
66
+ return cls(
67
+ FieldSeparatorStructureVersion=byte_array[0],
68
+ HeaderSize=byte_array[1],
69
+ FieldEntrySize=byte_array[2],
70
+ FieldEntryCount=byte_array[3],
71
+ SeparatorEntrySize=byte_array[4],
72
+ SeparatorEntryCount=byte_array[5],
73
+ MaxStorageSize=byte_array[6]
74
+ )
75
+
76
+ def to_bytes(self):
77
+ return bytes([self.FieldSeparatorStructureVersion,
78
+ self.HeaderSize,
79
+ self.FieldEntrySize,
80
+ self.FieldEntryCount,
81
+ self.SeparatorEntrySize,
82
+ self.SeparatorEntryCount,
83
+ self.MaxStorageSize])
@@ -0,0 +1,55 @@
1
+ from ctypes import Structure, c_uint8
2
+ from typing import Any
3
+
4
+ class HashData(Structure):
5
+ _fields_ = [
6
+ ("HashKeyA", c_uint8 * 16),
7
+ ("HashKeyB", c_uint8 * 16),
8
+ ("EnhanceSecurityFirmwareState", c_uint8)
9
+ ]
10
+
11
+ def __init__(self, *args: Any, **kw: Any):
12
+ super().__init__()
13
+ self.HashKeyA = (c_uint8 * 16)(*(kw.get("HashKeyA") or (args[0] if len(args) > 0 else [0]*16)))
14
+ self.HashKeyB = (c_uint8 * 16)(*(kw.get("HashKeyB") or (args[1] if len(args) > 1 else [0]*16)))
15
+ self.EnhanceSecurityFirmwareState = kw.get("EnhanceSecurityFirmwareState", args[2] if len(args) > 2 else 0)
16
+
17
+ def __str__(self):
18
+ hash_key_a_str = ', '.join([f'0x{b:02x}' for b in self.HashKeyA])
19
+ hash_key_b_str = ', '.join([f'0x{b:02x}' for b in self.HashKeyB])
20
+ return (
21
+ f"HashKeyA: [{hash_key_a_str}]\n"
22
+ f"HashKeyB: [{hash_key_b_str}]\n"
23
+ f"EnhanceSecurityFirmwareState: {self.EnhanceSecurityFirmwareState}\n"
24
+ )
25
+
26
+ def __repr__(self):
27
+ return self.__str__()
28
+
29
+ def __eq__(self, other):
30
+ return (
31
+ all(self.HashKeyA[i] == other.HashKeyA[i] for i in range(16))
32
+ and all(self.HashKeyB[i] == other.HashKeyB[i] for i in range(16))
33
+ and self.EnhanceSecurityFirmwareState == other.EnhanceSecurityFirmwareState
34
+ )
35
+
36
+ def __ne__(self, other):
37
+ return not self.__eq__(other)
38
+
39
+ def to_dict(self):
40
+ return {
41
+ "HashKeyA": [b for b in self.HashKeyA],
42
+ "HashKeyB": [b for b in self.HashKeyB],
43
+ "EnhanceSecurityFirmwareState": self.EnhanceSecurityFirmwareState
44
+ }
45
+
46
+ @classmethod
47
+ def from_bytes(cls, byte_array):
48
+ return cls(
49
+ HashKeyA=byte_array[0:16],
50
+ HashKeyB=byte_array[16:32],
51
+ EnhanceSecurityFirmwareState=byte_array[32]
52
+ )
53
+
54
+ def to_bytes(self):
55
+ return bytes(self.HashKeyA) + bytes(self.HashKeyB) + bytes([self.EnhanceSecurityFirmwareState])
@@ -0,0 +1,38 @@
1
+ from ctypes import Structure, c_uint8, c_int32
2
+ from typing import Any
3
+
4
+
5
+ class HidSeSamFirmwareVersion(Structure):
6
+ _pack_ = 1 # Ensure no padding between fields for native compatibility
7
+ _fields_ = [
8
+ ("Byte3", c_uint8),
9
+ ("Byte2", c_uint8),
10
+ ("Major", c_uint8),
11
+ ("Minor", c_uint8),
12
+ ("MicrocontrollerType", c_int32), # enum class in C++ uses int (4 bytes)
13
+ ("SamType", c_int32), # enum class in C++ uses int (4 bytes)
14
+ ]
15
+
16
+ def __init__(self, *args: Any, **kw: Any):
17
+ super().__init__()
18
+ self.Major = kw.get("Major", 0)
19
+ self.Minor = kw.get("Minor", 0)
20
+ self.Byte3 = kw.get("Byte3", 0)
21
+ self.Byte2 = kw.get("Byte2", 0)
22
+ self.MicrocontrollerType = kw.get("MicrocontrollerType", 0)
23
+ self.SamType = kw.get("SamType", 0)
24
+
25
+ def to_dict(self):
26
+ """Convert to dictionary."""
27
+ return {
28
+ "Byte3": self.Byte3,
29
+ "Byte2": self.Byte2,
30
+ "Major": self.Major,
31
+ "Minor": self.Minor,
32
+ "MicrocontrollerType": self.MicrocontrollerType,
33
+ "SamType": self.SamType,
34
+ }
35
+
36
+ def __str__(self):
37
+ return f"{self.Byte3}.{self.Byte2}.{self.Major}.{self.Minor}"
38
+
@@ -0,0 +1,13 @@
1
+ from ctypes import Structure, c_uint8, c_bool
2
+ from reader_integration_kit.enum.led_color import LedColor
3
+
4
+
5
+ class LedConfiguration(Structure):
6
+ _pack_ = 1
7
+ _fields_ = [
8
+ ("color", c_uint8),
9
+ ("software_control_enabled", c_bool),
10
+ ]
11
+
12
+ def __repr__(self):
13
+ return f"LedConfiguration(color={LedColor(self.color).name}, software_control_enabled={self.software_control_enabled})"