A Python-based RFID reader service for Raspberry Pi that reads RFID cards using the RC522 module and sends data to a webhook endpoint.
- RFID Card Reading: Continuously reads RFID cards using the RC522 module
- Webhook Integration: Sends card data to a configurable webhook URL
- Local Database Storage: SQLite database for storing all card reads with timestamps
- Offline Resilience: Stores events locally when offline and syncs when connection is restored
- Retry Logic: Exponential backoff retry system with up to 1 week persistence
- Write-Through Architecture: All card reads are immediately stored in database
- Device ID Management: Auto-generates unique device IDs or uses configured ones
- Background Service: Runs as a systemd service that starts on boot
- Logging: Comprehensive logging to both file and system journal
- Error Handling: Robust error handling with automatic service restart
- Raspbian Compatible: Designed specifically for Raspberry Pi running Raspbian OS
- Raspberry Pi (any model)
- RC522 RFID Reader Module
- RFID cards/tags
Connect the RC522 module to your Raspberry Pi as follows:
RC522 Pin | Raspberry Pi GPIO |
---|---|
SDA | GPIO 8 (Pin 24) |
SCK | GPIO 11 (Pin 23) |
MOSI | GPIO 10 (Pin 19) |
MISO | GPIO 9 (Pin 21) |
RST | GPIO 25 (Pin 22) |
VCC | 3.3V |
GND | GND |
-
Clone this repository:
git clone <repository-url> cd rfid-reader
-
Run the installation script:
sudo chmod +x install.sh sudo ./install.sh
-
Install system dependencies:
sudo apt-get update sudo apt-get install python3-pip python3-dev python3-venv
-
Create virtual environment and install dependencies:
sudo mkdir -p /opt/rfid_reader sudo python3 -m venv /opt/rfid_reader/venv sudo /opt/rfid_reader/venv/bin/pip install -r requirements.txt
-
Copy files to system locations:
sudo mkdir -p /etc/rfid_reader sudo cp rfid_reader.py /usr/local/bin/ sudo cp db_manager.py /usr/local/bin/ sudo cp config.toml /etc/rfid_reader/ sudo cp rfid-reader.service /etc/systemd/system/ sudo chmod +x /usr/local/bin/rfid_reader.py sudo chmod +x /usr/local/bin/db_manager.py # Update shebang to use virtual environment sudo sed -i '1s|#!/usr/bin/env python3|#!/opt/rfid_reader/venv/bin/python|' /usr/local/bin/rfid_reader.py sudo sed -i '1s|#!/usr/bin/env python3|#!/opt/rfid_reader/venv/bin/python|' /usr/local/bin/db_manager.py
-
Enable SPI interface:
echo "dtparam=spi=on" | sudo tee -a /boot/config.txt
-
Enable and start the service:
sudo systemctl daemon-reload sudo systemctl enable rfid-reader.service sudo systemctl start rfid-reader.service
Edit the configuration file at /etc/rfid_reader/config.toml
:
# Device ID (auto-generated if not set)
# device_id = "your_device_id_here"
# Webhook URL to send RFID data
webhook_url = "https://your-webhook-endpoint.com/rfid"
# API Key for webhook authentication (optional)
# api_key = "your_api_key_here"
# Optional: GPIO pins for RC522 (default values)
# sda_pin = 8
# sck_pin = 11
# mosi_pin = 10
# miso_pin = 9
# rst_pin = 25
# Optional: Logging level
# log_level = "INFO"
- device_id: Unique identifier for this device. If not set, a unique ID will be generated based on hardware information.
- webhook_url: URL where RFID data will be sent via POST requests.
- api_key: API key for webhook authentication. If set, will be included as
x-api-key
header. - GPIO pins: Customize the GPIO pins used for the RC522 module (optional).
- log_level: Set logging verbosity (DEBUG, INFO, WARNING, ERROR).
The service sends POST requests to your webhook URL with the following JSON payload:
{
"device_id": "abc123def456",
"card_id": "123456789",
"card_value": "John Doe"
}
- Content-Type:
application/json
- x-api-key:
your_api_key
(if api_key is configured in config.toml)
- device_id: The unique identifier for this RFID reader device
- card_id: The RFID card ID (unique hardware identifier)
- card_value: The text content stored on the RFID card (can be empty if no data is written)
sudo systemctl start rfid-reader.service
sudo systemctl stop rfid-reader.service
sudo systemctl status rfid-reader.service
# View systemd logs
sudo journalctl -u rfid-reader -f
# View application logs
sudo tail -f /var/log/rfid_reader.log
sudo systemctl restart rfid-reader.service
The RFID reader uses SQLite to store all card reads locally. The database is located at /var/lib/rfid_reader/card_reads.db
.
sudo db_manager.py stats
sudo db_manager.py recent --limit 50
sudo db_manager.py pending
sudo db_manager.py retry
sudo db_manager.py cleanup --days 30
sudo db_manager.py export /tmp/rfid_data.csv
-
Check if SPI is enabled:
grep spi /boot/config.txt
-
Check if SPI module is loaded:
lsmod | grep spi
-
View service logs:
sudo journalctl -u rfid-reader -n 50
- Verify wiring connections
- Check if the RC522 module is properly powered
- Ensure RFID cards are compatible with RC522
- Check GPIO pin configuration in config file
- Verify webhook URL is correct and accessible
- Check network connectivity
- View application logs for webhook errors:
sudo tail -f /var/log/rfid_reader.log
If the service is failing to start, run the diagnostic tool:
sudo diagnose.py
This will check:
- Python environment and dependencies
- File permissions and existence
- SPI interface configuration
- Database access
- Network connectivity
- Configuration file validity
If you see errors like [Errno 2] No such file or directory
related to SPI, run the SPI fix script:
sudo fix_spi.sh
This script will:
- Enable SPI in
/boot/config.txt
if not already enabled - Load the SPI kernel module
- Check for SPI device files
- Test GPIO access
Common issues and solutions:
- SPI not enabled: Run
sudo fix_spi.sh
or adddtparam=spi=on
to/boot/config.txt
and reboot - SPI module not loaded: Run
sudo fix_spi.sh
or reboot the system - Missing dependencies: Reinstall with
sudo ./install.sh
- Permission issues: Check file permissions and ownership
- Database directory: Ensure
/var/lib/rfid_reader
exists and is writable
-
Install dependencies:
pip3 install -r requirements.txt
-
Create a local config file:
cp config.toml local_config.toml # Edit local_config.toml with your settings
-
Run the script directly:
python3 rfid_reader.py
You can test the webhook functionality by modifying the read_card()
method to return a test card ID:
def read_card(self) -> Optional[str]:
# For testing without hardware
time.sleep(5) # Simulate card reading delay
return "test_card_123"
To test the webhook server with API key authentication:
# Start test server with API key
python3 test_webhook_server.py --api-key "your_test_api_key"
# In another terminal, test with curl
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-H "x-api-key: your_test_api_key" \
-d '{"device_id":"test123","card_id":"123456789","card_value":"John Doe"}'
This project is licensed under the MIT License - see the LICENSE file for details.
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly on Raspberry Pi
- Submit a pull request
For issues and questions:
- Check the troubleshooting section above
- View the logs for error messages
- Create an issue in the repository