Bir Raspberry Pi RFID MQTT kaydedici, bir kapıda, atölye makinesinde veya alet dolabında yapılan her kart okutmayı kaydeder ve bunu bilmesi gereken her sisteme gönderir: bir kayıt veritabanı, bir panel veya bir uyarı betiği. Bu eğitimde bir RC522 okuyucuyu bağlayacak, etiketleri Python ile okuyacak, bir etiketin izinli olup olmadığına yerel olarak karar verecek ve bilinmeyen kartlar için uyarılar dahil olmak üzere yapılandırılmış erişim olaylarını MQTT üzerinden yayınlayacaksınız.
Ne Oluşturacaksınız
Pi, şunları yapan tek bir Python servisi çalıştırır:
- RC522 okuyucuyu 13,56 MHz MIFARE kartlar ve anahtarlıklar için yoklar.
- Ham kimliğin cihazdan hiç çıkmaması için her etiketin UID'sinin hash'ini alır.
- Hash'i yerel bir izin listesi dosyasında arar ve izin verildi mi reddedildi mi karar verir.
- Her okutma için bir erişim olayı ve bilinmeyen etiketler için ayrı bir uyarı yayınlar.
- Retained bir "son erişim" mesajı ve bir çevrimiçi/çevrimdışı durumu tutar.
Erişim kararı bulutta değil, Pi üzerinde verilir. Böylece ağ kesikken de kapı çalışmaya devam eder; MQTT kayıt ve bildirim için kullanılır ki tam olarak iyi olduğu iş budur.
RC522'nin Kablolanması
RC522 modülü SPI ile konuşur ve yalnızca 3,3 V ile çalışır. Şöyle bağlayın:
| RC522 pini | Raspberry Pi fiziksel pini | İşlev |
|---|---|---|
| SDA (SS) | 24 | SPI CE0 |
| SCK | 23 | SPI saat |
| MOSI | 19 | SPI MOSI |
| MISO | 21 | SPI MISO |
| IRQ | Bağlı değil | |
| GND | 6 | Toprak |
| RST | 22 | GPIO25 |
| 3.3V | 1 | Güç |
Modülü asla 5 V'a bağlamayın. SPI'ı sudo raspi-config nonint do_spi 0 ile etkinleştirin ve yeniden başlatın; ardından ls /dev/spidev* komutu /dev/spidev0.0 listelemelidir.
Kütüphanelerin Kurulumu
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
mfrc522 paketi, Raspberry Pi 5'te çalışmayan RPi.GPIO paketine bağımlıdır. Bir Pi 5'te onu sanal ortam içinde uyumlu rpi-lgpio paketiyle değiştirin:
pip uninstall -y RPi.GPIO
pip install rpi-lgpio
MQTT eklemeden önce okuyucuyu test edin:
python -c "from mfrc522 import SimpleMFRC522; r = SimpleMFRC522(); print('Hold a tag near the reader'); print(r.read_id())"
Bir kartı veya anahtarlığı antene yaklaştırın; uzun bir sayı yazdırılmalıdır.
Olayları Tasarlamak
| Topic | Payload | QoS | Retained |
|---|---|---|---|
connectmq/demo/2fa7c1/door1/access |
Erişim olayı JSON | 1 | Hayır |
connectmq/demo/2fa7c1/door1/alert |
Bilinmeyen etiket JSON | 1 | Hayır |
connectmq/demo/2fa7c1/door1/last |
En son olay | 1 | Evet |
connectmq/demo/2fa7c1/door1/status |
online / offline |
1 | Evet |
Bir erişim olayı şöyle görünür:
{
"reader": "door1",
"tag": "a3f09b7c41de2280",
"name": "Alice",
"granted": true,
"ts": 1792163300
}
tag alanı UID'nin kendisi değil, UID'nin anahtarlı bir hash'idir. Genel bir broker'da ve genel olarak günlük dosyalarında ham UID etrafa yaymamanız gereken bir şeydir, çünkü düşük maliyetli kartlar ondan klonlanabilir.
İzin Listesi Dosyası
Proje klasöründe allowlist.json dosyasını oluşturun. Hash'leri ilk okutmalardan sonra dolduracaksınız:
{
"a3f09b7c41de2280": "Alice",
"51c2e8d4097fab13": "Workshop spare fob"
}
Yeni bir kart kaydetmek için onu bir kez okutun, uyarı mesajındaki tag değerini kopyalayın, bir adla birlikte dosyaya ekleyin ve yeniden yüklemesi için servise bir SIGHUP gönderin ya da onu basitçe yeniden başlatın.
Raspberry Pi RFID MQTT Betiği
rfid_mqtt.py olarak kaydedin:
#!/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 # card is still resting on the reader
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)
# Drive a door strike or LED here with GPIO.output() if granted.
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()
Debounce, okuyucunun üzerinde duran bir kartın saniyenin her onda birinde bir olay üretmesini engeller. paho, bağlantı kesikken QoS 1 mesajlarını bellekte kuyruğa aldığından, kısa bir ağ kesintisi sırasındaki okutmalar yeniden bağlandıktan sonra teslim edilir; max_queued_messages_set ise uzun bir kesintinin belleği tüketmemesi için bu kuyruğu sınırlar.
Akışı Test Etmek
Her şeyi başka bir terminalden izleyin:
mosquitto_sub -h broker.connectmq.com -p 1883 -i audit-2fa7c1 \
-t 'connectmq/demo/2fa7c1/door1/#' -v
Bilinmeyen bir kart okutun: "granted": false içeren bir access olayı ve aynı payload'u alert üzerinde göreceksiniz. Hash'ini allowlist.json dosyasına ekleyin, kill -HUP <pid> ile sürece bir SIGHUP gönderin ve adıyla birlikte "granted": true görmek için tekrar okutun.
Kayıt ve Uyarı
Okuyucu yalnızca yayın yapar; kalıcılık ve bildirim diğer MQTT istemcileri tarafından ele alınır, bu da cihazı basit tutar. Yaygın seçenekler şunlardır:
- Her
accessolayını SQLite'a yazan bir Python abonesi; Python ile MQTT verilerini SQLite'a kaydetme yazısında gösterildiği gibi. - Python ile MQTT e-posta uyarıları yazısındaki deseni kullanarak
alerttopic'inde bir e-posta veya sohbet bildirimi. - Retained
lastmesajını bir panelde gösteren bir Node-RED akışı. - Raspberry Pi röle MQTT kontrolcüsünü kullanan ikinci bir Pi tarafından sürülen bir kapı kilidi veya gösterge ışığı.
Ön Kapının Ötesinde
Aynı okuyucu ve olay biçimi başka birçok işe uyar. Bir makerspace'te bir lazer kesicinin veya torna tezgahının yanındaki okuyucu, makineyi kimin ve ne kadar süre kullandığını kaydedebilir: kart çekildiğinde ikinci bir olay yayınlayın, bir abone de oturum süresini hesaplayabilir. Bir sınıfta veya küçük bir ofiste yoklama için retained last topic'i canlı bir "kim yeni geldi" ekranı işlevi görür ve SQLite kaydı bir puantaj tablosuna dönüşür. Bir alet dolabında bir okutma bir çekmecenin kilidini açabilir ve onu hangi anahtarlığın açtığını kaydedebilir.
Her durumda yalnızca okuyucu adı ve topic öneki değişir. site1/workshop/lathe gibi konum başına bir önek seviyesi tutun; + joker karakterli tek bir abone her okuyucudan olayları toplayabilir. Alt akış araçlarının ihtiyaç duyduğu tek şey bir granted alanı ve kararlı bir hash'lenmiş tag değeridir; bu da cihaz kodunu tüm binada aynı tutar.
Kartı Okutan Kişiye Geri Bildirim
İnsanlar bir okutmanın işe yaradığını görmek veya duymak ister. Boş GPIO pinlerine yeşil ve kırmızı bir LED ya da küçük bir buzzer ekleyin ve karar verildikten hemen sonra bunları GPIO.output() ile sürün; okuyucu kütüphanesinin RPi.GPIO'yu zaten BOARD numaralandırma moduna aldığını unutmayın, bu yüzden fiziksel pin numaralarını kullanın. Yavaş bir ağda bile anında kalması için geri bildirimi bir MQTT gidiş-dönüşünü beklemek yerine yerel olarak verin.
Güvenlik Konuları
RFID projeleri fiziksel güvenliğe dokunur; bu yüzden sınırları konusunda gerçekçi olun. Temel MIFARE Classic kartlar ve birçok anahtarlık klonlanabilir; bu nedenle UID tabanlı bir sistem yüksek değerli alanları korumak için değil, kayıt, yoklama ve kolaylık amaçlı erişim için uygundur. Bunun ötesinde:
- Bir erişim sistemini asla genel test broker'ında çalıştırmayın. broker.connectmq.com üzerindeki her şey herkes tarafından okunabilir ve yalnızca ilk test içindir.
- Kimsenin sahte olay yayınlayamaması veya günlüklerinizi okuyamaması için TLS'li ve cihaz başına kimlik bilgili özel bir broker kullanın.
TAG_SECRETdeğerini kodun ve sürüm kontrolünün dışında tutun;chmod 600ile korunan bir systemd ortam dosyasında saklayın.- Bir ağ kesintisinin insanları dışarıda bırakmaması veya kapıyı açmaması için izin kararını yerel olarak verin.
Daha geniş rehberlik için MQTT güvenliği en iyi uygulamaları yazımızı okuyun.
Üretime Geçiş
ConnectMQ gibi barındırılan bir MQTT broker; 8883 portunda TLS, her client ID'ye bağlı oluşturulmuş kimlik bilgileri ve erişim olaylarının canlı topic gezginine gelişini izleyebileceğiniz bir portal sunar. Ortam değişkenlerini servis dosyanızda ayarlayın:
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
Raspberry Pi MQTT eğitimi, okuyucunun açılışta başlaması için uyarlayabileceğiniz bir systemd servis şablonu içerir.
ConnectMQ ile Başlayın
Erişim kayıtlarınıza özel, şifreli bir yol verin. Kredi kartı gerekmeden ConnectMQ'da ücretsiz bir Serverless broker oluşturun ve okuyucunuzu oluşturulan kimlik bilgileriyle TLS üzerinden bağlayın. Bu, kayıt aracınızın, panelinizin ve uyarı betiklerinizin sahada port açmadan erişebileceği bir bulut MQTT broker'dır.
Sık Sorulan Sorular
RC522 ile hangi RFID kartlar çalışır?
RC522, MIFARE Classic, MIFARE Ultralight ve birçok anahtarlık gibi 13,56 MHz ISO 14443A kartları okur. 125 kHz proximity kartları okumaz.
RFID UID'si yayınlanmadan önce neden hash'leniyor?
Ham bir UID basit kartları klonlamak için kullanılabilir ve MQTT mesajları çoğu zaman günlüklere düşer. Anahtarlı bir hash, UID'yi açığa çıkarmadan kartı yine de benzersiz biçimde tanımlar.
RC522, Raspberry Pi 5 üzerinde çalışır mı?
Evet, SPI etkinleştirilmiş ve mfrc522 kütüphanesinin beklediği RPi.GPIO yerine rpi-lgpio paketi kurulmuş olarak.
Ağ kesikken okutmalara ne olur?
Pi erişime yine yerel olarak karar verir. Servis çalışmaya devam ettiği sürece QoS 1 olayları bellekte kuyruğa alınır ve yeniden bağlandıktan sonra teslim edilir.



