Transport-agnostic driver library for the FI-50X UHF RFID reader (ISO-18000-6C)
Project description
python-fi50x
A transport-agnostic Python driver for the FI-50X UHF RFID reader (ISO-18000-6C / EPC Gen2) over its ASCII-over-UART protocol.
The library knows only the reader protocol — framing, the command set, typed responses, error-code handling and CRC-16 verification. It talks to a pluggable transport, so the same driver runs against a real serial port or a scripted fake in tests, and can be wrapped by any service (a RabbitMQ worker, a REST API, a CLI) on top.
- Import name:
fi50x - Distribution name:
python-fi50x(likepython-decouple→import decouple)
Features
- Inventory: single (
Q) and multi-tag (U,U<slotQ>) EPC reads, drained to completion and de-duplicated - Memory read/write (
R/W) with correct hex address/length framing and word-length validation - Tag management: access password (
P), kill (K), lock/unlock (L), select/filter (T) - Read-with-EPC (
UR/QR), TX power and frequency-regulation get/set - Typed results (
Tag,ReadResult,WriteResult) and a typed exception hierarchy for reader error codes - Gen2 CRC-16 verification of EPC reads
TagTrackerhelper to turn inventory sweeps into new/lost tag events- Thread-safe: a transport lock serialises full command/response transactions
Scope note: GPIO, frequency tuning, baud switching, command logging and the AA
binary protocol are not implemented yet. See doc/PROTOCOL.md
for the complete protocol reference.
Installation
pip install python-fi50x
Requires Python ≥ 3.8 and a serial connection to the reader (USB-UART). From source:
git clone https://github.com/pavelkim/python-fi50x
cd python-fi50x
pip install -e .[dev]
Quickstart
from fi50x import RFIDReader, Bank, Regulation
# Open the serial port (default baud 38400).
reader = RFIDReader.open("/dev/ttyUSB0")
print("firmware:", reader.firmware_version())
print("reader id:", reader.refresh_reader_id())
# Optional configuration
reader.set_regulation(Regulation.EU) # 865–868 MHz
reader.set_power_dbm(20) # register = dBm + 2, handled for you
# Inventory — read every tag currently in the field
for tag in reader.inventory().tags:
print(tag.epc, "crc_ok" if tag.crc_valid else "crc?")
# Read 4 words of USER memory, then write two words back
data = reader.read(Bank.USER, address=0, length=4).data
reader.write(Bank.USER, address=0, data="DEADBEEF") # leading zeros preserved
reader.close()
RFIDReader is also a context manager (with RFIDReader.open(port) as reader:).
For tests or non-serial links, construct it directly with a Transport:
RFIDReader(my_transport).
Continuous scanning with new/lost detection
from fi50x import RFIDReader, TagTracker
reader = RFIDReader.open("/dev/ttyUSB0")
tracker = TagTracker(miss_tolerance=2) # tolerate a couple of missed sweeps
for result in reader.stream_inventory(interval=0.1):
delta = tracker.update(tag.epc for tag in result.tags)
for epc in delta.new:
print("+ NEW ", epc)
for epc in delta.lost:
print("- LOST", epc)
A ready-to-run version of this is python-fi50x-scan.py:
./python-fi50x-scan.py --port /dev/ttyUSB0 --mode changes # only new/lost tags
./python-fi50x-scan.py --port /dev/ttyUSB0 --mode stream # every tag, every sweep
./python-fi50x-scan.py --help
Error handling
Reader error codes are raised as typed exceptions (all subclasses of
ReaderError), so callers can react to specific conditions:
from fi50x import MemoryLockedError, InsufficientPowerError, NoTagError
try:
reader.write(Bank.EPC, 2, "30001234")
except MemoryLockedError:
... # bank is locked
except InsufficientPowerError:
... # move the tag closer / raise power and retry
except NoTagError:
... # nothing in the field
Configuration
The example script reads config from CLI flags, falling back to environment
variables (a local .env is loaded if python-decouple
is installed). See .env.example:
| Variable | Default | Meaning |
|---|---|---|
SERIAL_PORT |
/dev/ttyUSB0 |
Serial device |
BAUDRATE |
38400 |
UART baud rate |
TIMEOUT |
0.5 |
Serial read timeout (s) |
TX_POWER |
20 |
TX power in dBm (−2…25) |
REGULATION |
05 |
Regulation code (05 = EU) |
Development
pip install -e .[dev]
pytest # run the test suite (no hardware needed — uses a fake transport)
tox # test across Python versions
tox -e build # build the sdist + wheel into dist/
Tests run entirely against a scripted FakeTransport, so no reader is required.
Protocol reference
The full FI-50X command specification — framing, every command, error codes, regulation and baud tables, examples and the Gen2 memory map — is in doc/PROTOCOL.md. Original vendor datasheets are in doc/.
License
MIT © Pavel Kim
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file python_fi50x-0.1.0.tar.gz.
File metadata
- Download URL: python_fi50x-0.1.0.tar.gz
- Upload date:
- Size: 21.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81c3c5d926d6e9c6c5ad6e11fda24e41ed1ccb0df3b05183286a7d715bfd2d66
|
|
| MD5 |
aea8f591983e0a5c21d60d91421fb6c3
|
|
| BLAKE2b-256 |
179181fd96da361f5f094b7bd1dee86515b1f1047f33c5eeffeb7319d200336b
|
Provenance
The following attestation bundles were made for python_fi50x-0.1.0.tar.gz:
Publisher:
release.yml on pavelkim/python-fi50x
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
python_fi50x-0.1.0.tar.gz -
Subject digest:
81c3c5d926d6e9c6c5ad6e11fda24e41ed1ccb0df3b05183286a7d715bfd2d66 - Sigstore transparency entry: 2124236539
- Sigstore integration time:
-
Permalink:
pavelkim/python-fi50x@47d527c25efa5dd5fb49813a2654887cb070d656 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/pavelkim
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@47d527c25efa5dd5fb49813a2654887cb070d656 -
Trigger Event:
push
-
Statement type:
File details
Details for the file python_fi50x-0.1.0-py3-none-any.whl.
File metadata
- Download URL: python_fi50x-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eccded3eb276f325077557c200fbfa0914512a1c1f799c988988327fe195d99b
|
|
| MD5 |
c3556abdc0086cfb7d0a87d6a26fff83
|
|
| BLAKE2b-256 |
887560452aa278e27bfdc475c95f822535a210de4711c456e3aeb09bf9793755
|
Provenance
The following attestation bundles were made for python_fi50x-0.1.0-py3-none-any.whl:
Publisher:
release.yml on pavelkim/python-fi50x
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
python_fi50x-0.1.0-py3-none-any.whl -
Subject digest:
eccded3eb276f325077557c200fbfa0914512a1c1f799c988988327fe195d99b - Sigstore transparency entry: 2124236586
- Sigstore integration time:
-
Permalink:
pavelkim/python-fi50x@47d527c25efa5dd5fb49813a2654887cb070d656 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/pavelkim
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@47d527c25efa5dd5fb49813a2654887cb070d656 -
Trigger Event:
push
-
Statement type: