Python API
The Python facade wraps the RIK native library using ctypes. Classes support the context manager protocol (with statement) for automatic resource cleanup.
Installation
Install from PyPI with a single command. pip selects the correct platform-tagged wheel automatically:
pip install reader-integration-kit
The wheel bundles the native shared library for your platform and CPU architecture
(manylinux_*_x86_64, manylinux_*_aarch64, manylinux_*_armv7l, win_amd64, or
macosx_12_0_universal2). The import name is reader_integration_kit on every platform.
On macOS, a single universal2 wheel covers both Intel (x86_64) and Apple Silicon (arm64)
-- no architecture-specific wheel selection is required. On Raspberry Pi 5 the ARM64
wheel bundles both the Pi 5-optimized and generic ARM64 libraries and selects the right
one at import time (override with RIK_ARM_VARIANT=pi5 or RIK_ARM_VARIANT=generic).
Older per-platform names such as reader-integration-kit-linux-x86-64 still resolve as
redirect packages.
Requirements: Python 3.8+
Package
import reader_integration_kit as rik
from reader_integration_kit.structures import ReaderDefinition, DeviceId, SerialPortSettings
from reader_integration_kit.enum import (
ProtocolType, BeepDuration, BeepVolume, LedColor,
ReaderModuleId, ReaderModuleState, BleDataType,
GetCardDataSizeParameters,
)
from reader_integration_kit.errors import ReaderException
AbstractReader (base class)
Base class for all reader applications. Supports the context manager protocol.
Methods
| Method | Returns | Description |
|---|---|---|
init() | None | Initialize connection to the reader |
refresh_metadata() | None | Force a metadata refresh from the device |
get_metadata(force_refresh=False) | dict | Get reader metadata |
get_library_info() | dict | Static. Get library version info (no instance required) |
dispose() | None | Release native resources |
init() is not called automatically -- you must call it explicitly after entering the with block. Exiting the with block calls dispose().
Always call init() after creating an instance or entering a with block. The constructor opens the connection but does not initialize communication with the reader.
Reader(AbstractReader)
Application class for rf IDEAS readers.
Constructor
Reader(reader_definition: ReaderDefinition, retry_count: int = 3)
| Parameter | Type | Description |
|---|---|---|
reader_definition | ReaderDefinition | Reader connection parameters |
retry_count | int | Connection retry attempts (default: 3) |
Methods
Beeper
| Method | Returns | Description |
|---|---|---|
beep(beep_count, duration) | None | Sound the beeper |
get_beeper_volume() | BeepVolume | Get current volume |
set_beeper_volume(volume) | None | Set volume |
Card Data
| Method | Returns | Description |
|---|---|---|
get_card_data(size_parameter=GetCardDataSizeParameters.READ_32_BYTES) | CardData | Read card data from the reader |
GetCardDataSizeParameters.READ_8_BYTES returns at most the first 8 bytes of the credential. The CardData buffer is still 32 bytes: bytes 0–7 hold the returned data and bytes 8–31 are zero. bit_count always reports the full credential width, so a bit count greater than 64 means the card carries more data than was returned. Prefer GetCardDataSizeParameters.READ_32_BYTES. See GetCardDataSizeParameters.
Credential Callbacks
| Method | Returns | Description |
|---|---|---|
on_credential_presented(callback, size_parameter=GetCardDataSizeParameters.READ_32_BYTES) | int | Subscribe to credential events. Returns a subscription ID. |
unsubscribe_credential_callback(subscription_id) | None | Unsubscribe a previously registered callback |
The callback signature is:
def my_callback(card_data: CardData) -> None:
...
When a card is presented to the reader, the callback fires with the card data. Multiple callbacks can be registered simultaneously.
There is one read size per reader instance. A later on_credential_presented call with a different size_parameter changes the payload delivered to all existing subscribers on that reader.
Configuration
| Method | Returns | Description |
|---|---|---|
get_reader_configuration(configuration_number) | tuple[ReaderConfigurationStruct, ExtendedConfiguration] | Read configuration slot |
set_reader_configuration(configuration_number, config, extended_config, hash_data) | None | Write configuration slot |
write_user_defaults_to_reader() | None | Copy the active flash configuration to stored (user-default) flash |
reset_reader_configuration(checkpoint_type) | None | Reset configuration to a checkpoint (CheckpointType.FACTORY_DEFAULTS or CheckpointType.USER_SETTINGS) |
If the extended configuration header is invalid, set_reader_configuration logs a warning and skips writing the extended configuration. The standard ReaderConfigurationStruct is still written. This path does not raise.
LED
| Method | Returns | Description |
|---|---|---|
get_led_configuration(configuration_number) | LedConfiguration | Read LED configuration |
set_led_configuration(configuration_number, led_configuration) | None | Write LED configuration |
LUID
| Method | Returns | Description |
|---|---|---|
get_luid() | LuidResponseInformation | Get Logical Unit ID |
set_luid(luid) | None | Set Logical Unit ID |
Module Control
| Method | Returns | Description |
|---|---|---|
get_module_state(module_id) | ReaderModuleState | Get module power state |
set_module_state(module_id, state) | None | Set module power state |
Modes
| Method | Returns | Description |
|---|---|---|
enable_keystroking(enable) | None | Enable or disable keystroking |
enable_transparent_mode(enable, write_to_flash) | None | Enable or disable transparent mode |
get_transparent_mode_status() | tuple[TransparentModeState, TransparentModeStatus] | Get transparent mode state and readiness |
Card Types
| Method | Returns | Description |
|---|---|---|
get_supported_card_types() | list[dict] | List supported card types |
BLE Configuration
| Method | Returns | Description |
|---|---|---|
read_ble_configuration_from_reader(data_type, file_name) | None | Read BLE config to file |
write_ble_configuration_to_reader(data_type, file_name) | None | Write BLE config from file |
HWG Configuration
| Method | Returns | Description |
|---|---|---|
write_hwg_file_to_reader(file_name) | None | Write an HWG configuration file to the reader |
read_hwg_file_from_reader(file_name, secure_hwg_format=True) | None | Read configuration from the reader and save to an HWG file |
Smart Card Configuration
| Method | Returns | Description |
|---|---|---|
write_smart_card_configuration_to_reader(file_name) | None | Write smart card configuration from an INI file to the reader |
read_smart_card_configuration_from_reader(config) | None | Read smart card configuration from the reader |
ReaderDiscovery
Discovers connected rf IDEAS USB readers. Returns ready-to-use ReaderDefinition objects that can be passed directly to the Reader constructor.
Methods
| Method | Returns | Description |
|---|---|---|
discover_usb_readers() | list[ReaderDefinition] | Static. Discovers all connected rf IDEAS USB readers |
Raises: ReaderException if USB enumeration fails.
from reader_integration_kit.facade import ReaderDiscovery
readers = ReaderDiscovery.discover_usb_readers()
for reader_def in readers:
print(f"VID:PID: 0x{reader_def.DeviceId.VendorId:04X}:0x{reader_def.DeviceId.ProductId:04X}")
print(f"Path: {reader_def.DeviceId.UsbPath.decode()}")
print(f"Serial: {reader_def.DeviceId.SerialNumber.decode()}")
See Discovering USB Readers for full examples including discover-then-connect patterns.
Structures
Defined in reader_integration_kit.structures. These are ctypes Structure subclasses.
ReaderDefinition
| Field | Type | Description |
|---|---|---|
DeviceId | DeviceId | Vendor and product identifiers |
ProtocolType | ProtocolType | Communication protocol |
SerialPortSettings | SerialPortSettings | Serial port configuration (serial connections only) |
DeviceId
| Field | Type | Description |
|---|---|---|
VendorId | int | USB vendor ID |
ProductId | int | USB product ID |
UsbPath | c_char * 512 | USB device path as UTF-8 byte string (optional). Set via b"..." literal. |
SerialNumber | c_char * 256 | USB serial number as UTF-8 byte string (optional). Set via b"..." literal. |
SerialPortSettings
| Field | Type |
|---|---|
BaudRate | SerialPortBaudRate |
Parity | SerialPortParity |
FlowControl | SerialPortFlowControl |
PortName | str |
ByteSize | int |
DataBits | SerialPortDataBits |
StopBits | SerialPortStopBits |
CardData
| Field / Method | Type | Description |
|---|---|---|
data | list[int] | Raw card data bytes (32-element list) |
bit_count | int | Number of valid bits |
is_empty() | bool | True if bit count is zero and all data bytes are zero |
as_bytes() | bytes | Card data as a bytes object |
as_list() | list[int] | Card data as a list of integers |
as_hex_string() | str | Space-separated hex representation (e.g. "12 34 AB") |
Enums
Defined in reader_integration_kit.enum.
ProtocolType
| Member | Value | Description |
|---|---|---|
INVALID | 0x00 | Invalid / unset |
FEATURE_REPORT | 0x01 | USB HID feature report |
SERIAL_BINARY | 0x03 | Serial binary protocol |
UNKNOWN | 0xFF | Unknown protocol |
BeepDuration
| Member | Value |
|---|---|
BEEP_DURATION_SHORT | 0 |
BEEP_DURATION_LONG | 1 |
BeepVolume
| Member | Value |
|---|---|
BEEP_VOLUME_OFF | 0 |
BEEP_VOLUME_LOW | 1 |
BEEP_VOLUME_MEDIUM | 2 |
BEEP_VOLUME_HIGH | 3 |
LedColor
| Member | Value |
|---|---|
INVALID | 0 |
OFF | 1 |
RED | 2 |
GREEN | 3 |
AMBER | 4 |
UNKNOWN | 0xFF |
ReaderModuleId
| Member | Value |
|---|---|
INVALID | 0 |
LOW_FREQUENCY_RADIO | 1 |
HIGH_FREQUENCY_RADIO | 2 |
BLE_RADIO | 3 |
ReaderModuleState
| Member | Value | Description |
|---|---|---|
INVALID | 0x00 | Not set |
POWER_OFF | 0x80 | Module powered off |
POWER_ON_NORMAL | 0x81 | Module powered on, normal operation |
BleDataType
| Member | Value | Description |
|---|---|---|
DATA | 1 | BLE data payload |
KEY | 2 | Encrypted key |
UNENCRYPTED_KEY | 3 | Unencrypted key |
GetCardDataSizeParameters
| Member | Value | Description |
|---|---|---|
UNDEFINED | 0x00 | Invalid / unset — do not pass |
READ_8_BYTES | 0x01 | 8-byte read |
READ_32_BYTES | 0x02 | 32-byte read (default) |
CardCategory
| Member | Value | Description |
|---|---|---|
OFF | 0 | Category not applicable / disabled |
SECURE | 1 | Secure credential |
NON_SECURE | 2 | Non-secure credential |
BLUETOOTH | 3 | Bluetooth / mobile credential |
CardFrequency
| Member | Value | Description |
|---|---|---|
NA | 0 | Frequency not applicable |
BLE | 1 | Bluetooth Low Energy RF |
HIGH | 2 | High frequency |
LOW | 3 | Low frequency |
DUAL | 4 | Dual frequency |
Errors
ReaderException
Raised on any native library error.
| Attribute | Type | Description |
|---|---|---|
message | str | Error description |
file_name | str | Source file |
line_number | int | Source line |
function_name | str | Source function |
has_protocol_exception | bool | Whether protocol-level details are available |
protocol_message | str | Protocol error description |
Examples
Basic Connection
import reader_integration_kit as rik
from reader_integration_kit.structures import ReaderDefinition, DeviceId
from reader_integration_kit.enum import ProtocolType
reader_def = ReaderDefinition()
reader_def.DeviceId.VendorId = 0x0C27
reader_def.DeviceId.ProductId = 0x3BFA
reader_def.ProtocolType = ProtocolType.FEATURE_REPORT
with rik.Reader(reader_def) as app:
app.init()
metadata = app.get_metadata()
print(f"Part: {metadata['PartNumber']}")
print(f"Serial: {metadata['ESN']}")
Beep
with rik.Reader(reader_def) as app:
app.init()
app.beep(2, BeepDuration.BEEP_DURATION_SHORT)
app.set_beeper_volume(BeepVolume.BEEP_VOLUME_HIGH)
Read Card Data
with rik.Reader(reader_def) as app:
app.init()
card = app.get_card_data()
if card.bit_count > 0:
print(f"Bits: {card.bit_count}")
print(f"Data: {card.data}")
from reader_integration_kit.enum import GetCardDataSizeParameters
with rik.Reader(reader_def) as app:
app.init()
# 8-byte read
card = app.get_card_data(size_parameter=GetCardDataSizeParameters.READ_8_BYTES)
if card.bit_count > 64:
# data was truncated; bytes 8-31 are zero
pass
Metadata
with rik.Reader(reader_def) as app:
app.init()
# Cached metadata
metadata = app.get_metadata()
# Force refresh from device
metadata = app.get_metadata(force_refresh=True)
Library Info (No Reader Required)
info = rik.AbstractReader.get_library_info()
print(f"Version: {info['VersionString']}")
Error Handling
from reader_integration_kit.errors import ReaderException
try:
with rik.Reader(reader_def) as app:
app.init()
card = app.get_card_data()
except ReaderException as e:
print(f"Error: {e.message}")
if e.has_protocol_exception:
print(f"Protocol: {e.protocol_message}")
Thread Safety
All methods are thread-safe. Internal locking ensures safe concurrent access.