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.
- reader_integration_kit/__init__.py +12 -0
- reader_integration_kit/enum/__init__.py +28 -0
- reader_integration_kit/enum/beep_duration.py +12 -0
- reader_integration_kit/enum/beep_volume.py +15 -0
- reader_integration_kit/enum/ble_data_type.py +12 -0
- reader_integration_kit/enum/blob_type.py +27 -0
- reader_integration_kit/enum/checkpoint_type.py +13 -0
- reader_integration_kit/enum/data_conversion_type.py +12 -0
- reader_integration_kit/enum/field_definition_type.py +14 -0
- reader_integration_kit/enum/led_color.py +15 -0
- reader_integration_kit/enum/protocol_type.py +14 -0
- reader_integration_kit/enum/proximity_card_type.py +166 -0
- reader_integration_kit/enum/reader_module_id.py +13 -0
- reader_integration_kit/enum/reader_module_state.py +12 -0
- reader_integration_kit/enum/serial_port_baud_rate.py +15 -0
- reader_integration_kit/enum/serial_port_data_bits.py +10 -0
- reader_integration_kit/enum/serial_port_flow_control.py +11 -0
- reader_integration_kit/enum/serial_port_parity.py +10 -0
- reader_integration_kit/enum/serial_port_stop_bits.py +9 -0
- reader_integration_kit/enum/transparent_mode_state.py +11 -0
- reader_integration_kit/enum/transparent_mode_status.py +11 -0
- reader_integration_kit/errors/__init__.py +4 -0
- reader_integration_kit/errors/reader_exception.py +58 -0
- reader_integration_kit/facade/__init__.py +882 -0
- reader_integration_kit/lib/ReaderIntegrationKit.dll +0 -0
- reader_integration_kit/structures/__init__.py +36 -0
- reader_integration_kit/structures/blob_header.py +54 -0
- reader_integration_kit/structures/bluetooth_firmware_version.py +35 -0
- reader_integration_kit/structures/card_data.py +77 -0
- reader_integration_kit/structures/card_type_info.py +51 -0
- reader_integration_kit/structures/device_id.py +12 -0
- reader_integration_kit/structures/extended_configuration.py +32 -0
- reader_integration_kit/structures/felica_sam_firmware_version.py +38 -0
- reader_integration_kit/structures/field_entry.py +120 -0
- reader_integration_kit/structures/field_separator_data_header.py +83 -0
- reader_integration_kit/structures/hash_data.py +55 -0
- reader_integration_kit/structures/hid_se_sam_firmware_version.py +38 -0
- reader_integration_kit/structures/led_configuration.py +13 -0
- reader_integration_kit/structures/library_info.py +74 -0
- reader_integration_kit/structures/luid_response_information.py +44 -0
- reader_integration_kit/structures/microcontroller_firmware_version.py +38 -0
- reader_integration_kit/structures/nxp_sam_firmware_version.py +38 -0
- reader_integration_kit/structures/reader_configuration.py +171 -0
- reader_integration_kit/structures/reader_data.py +49 -0
- reader_integration_kit/structures/reader_definition.py +14 -0
- reader_integration_kit/structures/reader_metadata_struct.py +195 -0
- reader_integration_kit/structures/rik_result.py +71 -0
- reader_integration_kit/structures/separator_character.py +44 -0
- reader_integration_kit/structures/separator_entry.py +73 -0
- reader_integration_kit/structures/serial_port_settings.py +45 -0
- reader_integration_kit/structures/smart_card_configuration.py +34 -0
- reader_integration_kit-1.4.2.dist-info/METADATA +139 -0
- reader_integration_kit-1.4.2.dist-info/RECORD +56 -0
- reader_integration_kit-1.4.2.dist-info/WHEEL +5 -0
- reader_integration_kit-1.4.2.dist-info/licenses/rfIDEAS_EULA.txt +281 -0
- reader_integration_kit-1.4.2.dist-info/top_level.txt +1 -0
|
Binary file
|
|
@@ -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,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})"
|