Raspberry Pi

Raspberry Pi RFID MQTT: Zutrittsprotokollierung mit dem RC522-Leser

Schließen Sie einen RC522-RFID-Leser an einen Raspberry Pi an, lesen Sie Tags mit Python, prüfen Sie sie gegen eine lokale Allowlist und veröffentlichen Sie jeden Zutrittsversuch als MQTT-Ereignis, das Logger, Dashboards und Alarmwerkzeuge verarbeiten können.

RC522-RFID-Leser an einem Raspberry Pi neben einer Tür, eine Karte wird gescannt und ein Zutrittsereignis in einem Raspberry Pi RFID MQTT Projekt in die Cloud gesendet
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

Ein Raspberry Pi RFID MQTT Logger erfasst jeden Badge-Scan an einer Tür, einer Werkstattmaschine oder einem Werkzeugschrank und sendet ihn an jedes System, das davon wissen muss: eine Protokolldatenbank, ein Dashboard oder ein Alarmskript. In diesem Tutorial verdrahten Sie einen RC522-Leser, lesen Tags mit Python, entscheiden lokal, ob ein Tag zugelassen ist, und veröffentlichen strukturierte Zutrittsereignisse über MQTT, einschließlich Alarmen für unbekannte Karten.

Was Sie bauen

Auf dem Pi läuft ein Python-Dienst, der:

  1. Den RC522-Leser auf 13,56-MHz-MIFARE-Karten und Schlüsselanhänger abfragt.
  2. Die UID jedes Tags hasht, sodass die rohe ID das Gerät nie verlässt.
  3. Den Hash in einer lokalen Allowlist-Datei nachschlägt und über Zutritt gewährt oder verweigert entscheidet.
  4. Für jeden Scan ein Zutrittsereignis und für unbekannte Tags einen separaten Alarm veröffentlicht.
  5. Eine retained Nachricht „letzter Zutritt“ sowie einen Online-/Offline-Status vorhält.

Die Zutrittsentscheidung fällt auf dem Pi, nicht in der Cloud. So funktioniert die Tür auch bei Netzausfall weiter; MQTT dient der Protokollierung und Benachrichtigung, und genau darin ist es stark.

Den RC522 verdrahten

Das RC522-Modul spricht SPI und läuft ausschließlich mit 3,3 V. Verbinden Sie es so:

RC522-Pin Physischer Pin am Raspberry Pi Funktion
SDA (SS) 24 SPI CE0
SCK 23 SPI-Takt
MOSI 19 SPI MOSI
MISO 21 SPI MISO
IRQ Nicht verbunden
GND 6 Masse
RST 22 GPIO25
3.3V 1 Versorgung

Schließen Sie das Modul niemals an 5 V an. Aktivieren Sie SPI mit sudo raspi-config nonint do_spi 0 und starten Sie neu; danach sollte ls /dev/spidev* den Eintrag /dev/spidev0.0 zeigen.

Die Bibliotheken installieren

sudo apt update
sudo apt install -y python3-venv python3-dev
mkdir -p ~/rfid-mqtt && cd ~/rfid-mqtt
python3 -m venv .venv
source .venv/bin/activate
pip install "paho-mqtt>=2.0" mfrc522 spidev

Das Paket mfrc522 hängt von RPi.GPIO ab, das auf dem Raspberry Pi 5 nicht funktioniert. Ersetzen Sie es auf einem Pi 5 innerhalb der virtuellen Umgebung durch das kompatible Paket rpi-lgpio:

pip uninstall -y RPi.GPIO
pip install rpi-lgpio

Testen Sie den Leser, bevor Sie MQTT hinzufügen:

python -c "from mfrc522 import SimpleMFRC522; r = SimpleMFRC522(); print('Hold a tag near the reader'); print(r.read_id())"

Halten Sie eine Karte oder einen Anhänger an die Antenne; es sollte eine lange Zahl ausgegeben werden.

Die Ereignisse entwerfen

Topic Payload QoS Retained
connectmq/demo/2fa7c1/door1/access Zutrittsereignis als JSON 1 Nein
connectmq/demo/2fa7c1/door1/alert Unbekannter Tag als JSON 1 Nein
connectmq/demo/2fa7c1/door1/last Letztes Ereignis 1 Ja
connectmq/demo/2fa7c1/door1/status online / offline 1 Ja

Ein Zutrittsereignis sieht so aus:

{
  "reader": "door1",
  "tag": "a3f09b7c41de2280",
  "name": "Alice",
  "granted": true,
  "ts": 1792163300
}

Das Feld tag ist ein mit Schlüssel gebildeter Hash der UID, nicht die UID selbst. Auf einem öffentlichen MQTT-Broker und in Protokolldateien allgemein sollten Sie eine rohe UID nicht verbreiten, denn günstige Karten lassen sich damit klonen.

Die Allowlist-Datei

Legen Sie allowlist.json im Projektordner an. Die Hashes tragen Sie nach den ersten Scans ein:

{
  "a3f09b7c41de2280": "Alice",
  "51c2e8d4097fab13": "Workshop spare fob"
}

Um eine neue Karte anzulernen, scannen Sie sie einmal, kopieren den tag-Wert aus der Alarmnachricht, tragen ihn mit einem Namen in die Datei ein und senden dem Dienst ein SIGHUP zum Neuladen, oder starten ihn einfach neu.

Das Raspberry Pi RFID MQTT-Skript

Speichern Sie es als rfid_mqtt.py:

#!/usr/bin/env python3
"""RC522 access logging over MQTT."""
import hashlib
import hmac
import json
import os
import signal
import time
import uuid
from pathlib import Path

import paho.mqtt.client as mqtt
import RPi.GPIO as GPIO
from mfrc522 import SimpleMFRC522

BROKER = os.getenv("MQTT_HOST", "broker.connectmq.com")
PORT = int(os.getenv("MQTT_PORT", "1883"))
USERNAME = os.getenv("MQTT_USERNAME")
PASSWORD = os.getenv("MQTT_PASSWORD")
CLIENT_ID = os.getenv("MQTT_CLIENT_ID", f"rfid-{uuid.uuid4().hex[:8]}")
PREFIX = os.getenv("MQTT_PREFIX", "connectmq/demo/2fa7c1/door1")
READER_NAME = os.getenv("READER_NAME", "door1")
SECRET = os.getenv("TAG_SECRET", "change-me-to-a-long-random-string").encode()
ALLOWLIST_FILE = Path(os.getenv("ALLOWLIST", "allowlist.json"))
DEBOUNCE_S = 3

reader = SimpleMFRC522()
allowlist = {}


def load_allowlist(*_):
    global allowlist
    try:
        allowlist = json.loads(ALLOWLIST_FILE.read_text())
        print(f"Loaded {len(allowlist)} allowed tags")
    except (OSError, json.JSONDecodeError) as err:
        print(f"Could not load allowlist: {err}")


def tag_hash(uid: int) -> str:
    digest = hmac.new(SECRET, str(uid).encode(), hashlib.sha256).hexdigest()
    return digest[:16]


def on_connect(client, userdata, flags, reason_code, properties):
    if reason_code.is_failure:
        print(f"Connection refused: {reason_code}")
        return
    print(f"Connected as {CLIENT_ID}")
    client.publish(f"{PREFIX}/status", "online", qos=1, retain=True)


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.on_connect = on_connect
client.will_set(f"{PREFIX}/status", "offline", qos=1, retain=True)
client.reconnect_delay_set(min_delay=1, max_delay=60)
client.max_queued_messages_set(500)
if USERNAME:
    client.username_pw_set(USERNAME, PASSWORD)
if PORT == 8883:
    client.tls_set()

load_allowlist()
signal.signal(signal.SIGHUP, load_allowlist)
client.connect(BROKER, PORT, keepalive=30)
client.loop_start()

last_tag, last_time = None, 0.0
try:
    while True:
        uid = reader.read_id_no_block()
        if uid is None:
            time.sleep(0.1)
            continue
        tag = tag_hash(uid)
        now = time.time()
        if tag == last_tag and now - last_time < DEBOUNCE_S:
            continue  # Karte liegt noch auf dem Leser
        last_tag, last_time = tag, now

        name = allowlist.get(tag)
        event = {
            "reader": READER_NAME,
            "tag": tag,
            "name": name,
            "granted": name is not None,
            "ts": int(now),
        }
        payload = json.dumps(event)
        client.publish(f"{PREFIX}/access", payload, qos=1)
        client.publish(f"{PREFIX}/last", payload, qos=1, retain=True)
        if name is None:
            client.publish(f"{PREFIX}/alert", payload, qos=1)
        print(event)
        # Bei gewährtem Zutritt hier Türöffner oder LED mit GPIO.output() ansteuern.
except KeyboardInterrupt:
    pass
finally:
    client.publish(f"{PREFIX}/status", "offline", qos=1, retain=True).wait_for_publish(2)
    client.loop_stop()
    client.disconnect()
    GPIO.cleanup()

Die Entprellung verhindert, dass eine auf dem Leser liegende Karte jede Zehntelsekunde ein Ereignis erzeugt. Weil paho QoS-1-Nachrichten bei unterbrochener Verbindung im Speicher puffert, werden Scans während eines kurzen Netzausfalls nach der Wiederverbindung zugestellt; max_queued_messages_set begrenzt diese Warteschlange, damit ein langer Ausfall den Speicher nicht erschöpft.

Den Ablauf testen

Beobachten Sie alles in einem anderen Terminal:

mosquitto_sub -h broker.connectmq.com -p 1883 -i audit-2fa7c1 \
  -t 'connectmq/demo/2fa7c1/door1/#' -v

Scannen Sie eine unbekannte Karte: Sie sehen ein access-Ereignis mit "granted": false und dieselbe Payload auf alert. Tragen Sie den Hash in allowlist.json ein, senden Sie dem Prozess mit kill -HUP <pid> ein SIGHUP und scannen Sie erneut, um "granted": true mit dem Namen zu sehen.

Protokollierung und Alarmierung

Der Leser veröffentlicht nur; Speicherung und Benachrichtigung übernehmen andere MQTT-Clients, was das Gerät einfach hält. Gängige Optionen sind:

  1. Ein Python-Abonnent, der jedes access-Ereignis in SQLite schreibt, wie in MQTT-Daten mit Python in SQLite speichern gezeigt.
  2. Eine E-Mail- oder Chat-Benachrichtigung auf dem alert-Topic nach dem Muster aus MQTT-E-Mail-Alarme mit Python.
  3. Ein Node-RED-Flow, der die retained last-Nachricht auf einem Dashboard anzeigt.
  4. Ein Türöffner oder eine Signalleuchte, angesteuert von einem zweiten Pi mit der Steuerung Raspberry Pi Relais über MQTT.

Über die Eingangstür hinaus

Derselbe Leser und dasselbe Ereignisformat passen zu weiteren Aufgaben. In einem Makerspace kann ein Leser neben einem Laserschneider oder einer Drehmaschine protokollieren, wer die Maschine wie lange genutzt hat: Veröffentlichen Sie ein zweites Ereignis, wenn die Karte entfernt wird, und ein Abonnent kann die Nutzungsdauer berechnen. Für die Anwesenheitserfassung in einem Schulungsraum oder kleinen Büro dient das retained last-Topic zugleich als Live-Anzeige „wer gerade angekommen ist“, und das SQLite-Protokoll wird zum Stundenzettel. In einem Werkzeugschrank kann ein Scan eine Schublade entriegeln und festhalten, welcher Anhänger sie geöffnet hat.

In jedem Fall ändern sich nur der Lesername und das Topic-Präfix. Verwenden Sie eine Präfixebene pro Ort, etwa site1/workshop/lathe, dann kann ein einziger Abonnent mit einem +-Wildcard die Ereignisse aller Leser einsammeln. Ein Feld granted und ein stabiler gehashter tag sind alles, was die nachgelagerten Werkzeuge brauchen, sodass der Gerätecode im ganzen Gebäude identisch bleibt.

Rückmeldung für die scannende Person

Menschen erwarten, zu sehen oder zu hören, dass ein Scan funktioniert hat. Ergänzen Sie an freien GPIO-Pins eine grüne und eine rote LED oder einen kleinen Summer und steuern Sie sie direkt nach der Entscheidung mit GPIO.output() an; beachten Sie, dass die Leser-Bibliothek RPi.GPIO bereits in den BOARD-Nummerierungsmodus versetzt, verwenden Sie also physische Pinnummern. Geben Sie die Rückmeldung lokal, statt auf einen MQTT-Roundtrip zu warten, damit sie auch in einem langsamen Netz sofort erfolgt.

Sicherheitsaspekte

RFID-Projekte berühren die physische Sicherheit, seien Sie also realistisch, was ihre Grenzen angeht. Einfache MIFARE-Classic-Karten und viele Anhänger lassen sich klonen. Ein UID-basiertes System eignet sich deshalb für Protokollierung, Anwesenheitserfassung und komfortablen Zutritt, nicht für den Schutz hochwertiger Bereiche. Außerdem gilt:

  • Betreiben Sie niemals ein Zutrittssystem auf dem öffentlichen MQTT-Broker. Alles auf broker.connectmq.com ist für jeden lesbar und nur für den ersten Test gedacht.
  • Verwenden Sie einen privaten Broker mit TLS und Zugangsdaten pro Gerät, damit niemand gefälschte Ereignisse veröffentlichen oder Ihre Protokolle lesen kann.
  • Halten Sie TAG_SECRET aus dem Code und aus der Versionsverwaltung heraus; speichern Sie es in einer systemd-Umgebungsdatei mit chmod 600.
  • Treffen Sie die Zutrittsentscheidung lokal, damit ein Netzausfall niemanden aussperrt oder die Tür öffnet.

Weiterführende Hinweise finden Sie in unseren Best Practices zur MQTT-Sicherheit.

Der Weg in die Produktion

Ein verwalteter MQTT-Broker wie ConnectMQ bietet TLS auf Port 8883, generierte Zugangsdaten, die an jede Client ID gebunden sind, und ein Portal, in dem Sie im Live-Topic-Explorer verfolgen, wie Zutrittsereignisse eintreffen. Setzen Sie die Umgebungsvariablen in Ihrer Service-Datei:

MQTT_HOST=broker.connectmq.com
MQTT_PORT=8883
MQTT_USERNAME=YOUR_USERNAME
MQTT_PASSWORD=YOUR_PASSWORD
MQTT_CLIENT_ID=YOUR_CLIENT_ID
MQTT_PREFIX=site1/building-a/door1
TAG_SECRET=a-long-random-secret

Das Raspberry Pi MQTT Tutorial enthält eine systemd-Service-Vorlage, die Sie anpassen können, damit der Leser beim Booten startet.

Starten Sie mit ConnectMQ

Geben Sie Ihren Zutrittsprotokollen einen privaten, verschlüsselten Weg. Erstellen Sie einen kostenlosen Serverless-Broker bei ConnectMQ, ohne Kreditkarte, und verbinden Sie Ihren Leser mit den generierten Zugangsdaten per TLS. Es ist ein Cloud-MQTT-Broker, den Ihr Logger, Ihr Dashboard und Ihre Alarmskripte erreichen, ohne dass am Standort Ports geöffnet werden müssen.

Häufig gestellte Fragen

Welche RFID-Karten funktionieren mit dem RC522?

Der RC522 liest 13,56-MHz-Karten nach ISO 14443A wie MIFARE Classic, MIFARE Ultralight und viele Schlüsselanhänger. 125-kHz-Proximity-Karten liest er nicht.

Warum wird die RFID-UID vor dem Veröffentlichen gehasht?

Mit einer rohen UID lassen sich einfache Karten klonen, und MQTT-Nachrichten landen oft in Protokollen. Ein Hash mit Schlüssel identifiziert die Karte weiterhin eindeutig, ohne die UID preiszugeben.

Funktioniert der RC522 auf einem Raspberry Pi 5?

Ja, mit aktiviertem SPI und dem Paket rpi-lgpio, installiert anstelle von RPi.GPIO, das die Bibliothek mfrc522 erwartet.

Was passiert mit Scans, wenn das Netzwerk ausfällt?

Der Pi entscheidet weiterhin lokal über den Zutritt. QoS-1-Ereignisse werden im Speicher gepuffert und nach der Wiederverbindung zugestellt, solange der Dienst weiterläuft.

Verwandte Artikel

Pico W vs. Pico 2 W für MQTT: RP2040 vs. RP2350 bei Leistung, Speicher und TLS

Der Pico 2 W behält Formfaktor und WLAN-Chip des Pico W, ersetzt aber den RP2040 durch den schnelleren RP2350. Dieser Vergleich zeigt, was das für MQTT-Geräte bedeutet: CPU, Speicher, TLS, Sicherheitsfunktionen, Softwareunterstützung und welches Board für welches Projekt.

8 Min. Lesezeit

Mosquitto auf dem Raspberry Pi installieren: sicherer lokaler MQTT-Broker

Installieren Sie Mosquitto auf einem Raspberry Pi, sichern Sie ihn mit Passwörtern und einer durchdachten Listener-Konfiguration ab, testen Sie ihn mit mosquitto_pub und mosquitto_sub und erfahren Sie, wann ein lokaler Broker per Bridge an einen Cloud-MQTT-Broker angebunden werden sollte.

8 Min. Lesezeit

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.