Raspberry Pi

RC522 Okuyucu ile Raspberry Pi RFID MQTT Erişim Kaydı

Bir RC522 RFID okuyucuyu Raspberry Pi'ye bağlayın, etiketleri Python ile okuyun, yerel bir izin listesiyle karşılaştırın ve her erişim denemesini kayıt araçlarının, panellerin ve uyarı araçlarının tüketebileceği bir MQTT olayı olarak yayınlayın.

Bir raspberry pi rfid mqtt projesinde kapının yanında Raspberry Pi'ye bağlı RC522 RFID okuyucu, okutulan bir kart ve buluta gönderilen erişim olayı
Bunu kendi MQTT broker’ınızda çalıştırınFree planla özel, yönetilen bir MQTT broker alın ve hazır kod örnekleriyle başlayın.
Ücretsiz deneyin Kod örnekleri Kart gerekmez

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:

  1. RC522 okuyucuyu 13,56 MHz MIFARE kartlar ve anahtarlıklar için yoklar.
  2. Ham kimliğin cihazdan hiç çıkmaması için her etiketin UID'sinin hash'ini alır.
  3. Hash'i yerel bir izin listesi dosyasında arar ve izin verildi mi reddedildi mi karar verir.
  4. Her okutma için bir erişim olayı ve bilinmeyen etiketler için ayrı bir uyarı yayınlar.
  5. 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:

  1. Her access olayını SQLite'a yazan bir Python abonesi; Python ile MQTT verilerini SQLite'a kaydetme yazısında gösterildiği gibi.
  2. Python ile MQTT e-posta uyarıları yazısındaki deseni kullanarak alert topic'inde bir e-posta veya sohbet bildirimi.
  3. Retained last mesajını bir panelde gösteren bir Node-RED akışı.
  4. 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_SECRET değerini kodun ve sürüm kontrolünün dışında tutun; chmod 600 ile 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.

İlgili yazılar

Python ve Bleak ile Raspberry Pi BLE'den MQTT'ye Köprü

Raspberry Pi'nin dahili Bluetooth'unu, bleak kütüphanesini ve paho-mqtt'yi kullanarak BLE sensör yayın paketlerini tarayın, sıcaklık ve nemi çözün ve hız sınırlı ölçümleri MQTT'ye yayınlayın.

6 dk okuma

Tüm yazılar →

Özel MQTT broker’ınız birkaç tık uzağınızda

Hesabınızı oluşturun, broker kimlik bilgilerinizi alın ve ilk cihazınızı bağlayın — kurulacak, yamalanacak ya da ölçeklendirilecek sunucu yok.