RFIDを使った出席管理システムの構築
RFID技術を活用して、出席管理を自動化する方法をご紹介します。この記事では、SonyのRC-S380/S NFCリーダーを使用して、出席データを収集し、MongoDBに記録するシステムの作り方を説明します。
必要な機材とソフトウェア
- Sony RC-S380/S NFCリーダー
- NFCタグ(Suica)
- Python 3.9
- MongoDB
システム概要
このシステムは、以下の2つの主要コンポーネントから構成されます。
-
RFID読み取りプログラム (
rfid.py
): NFCリーダーでタグを読み取り、MongoDBに記録します。 -
Webインターフェース (
web.py
): Flaskで構築したWebアプリケーションで、記録された出席データを表示します。
環境設定
MongoDBのインストールと設定
MongoDBはNoSQLデータベースで、以下の公式ウェブサイトからダウンロードしてください。
# MongoDBのセットアップ
mongo
use attendance
db.createCollection("records")
RFID読み取りプログラム (rfid.py)
RFIDタグの情報を読み取り、MongoDBに記録するためのプログラム
import nfc
import pymongo
import datetime
# MongoDBのセットアップ
client = pymongo.MongoClient("mongodb://111.1.1.1:11111/") #自分のアドレスを設定
db = client["attendance"]
collection = db["records"]
# NFCリーダーの初期化
clf = nfc.ContactlessFrontend('usb')
try:
while True:
# NFCタグの読み取り
tag = clf.connect(rdwr={'on-connect': lambda tag: False})
if tag:
tag_id = tag.identifier.hex()
print(f"Detected NFC Tag with ID: {tag_id}")
# 現在のタイムスタンプ
timestamp = datetime.datetime.now()
# データベースに保存
collection.insert_one({"tag_id": tag_id, "timestamp": timestamp})
print("Data saved to MongoDB")
except KeyboardInterrupt:
# ユーザーがプログラムを中断するまでループ
pass
finally:
clf.close()
print("NFC reader closed")
Webインターフェース (web.py)
Flaskを使って構築したWebアプリケーションのコード
from flask import Flask, render_template
import pymongo
import csv
def read_csv_file(filename):
with open(filename, mode='r', encoding='utf-8') as file:
reader = csv.DictReader(file)
return list(reader)
app = Flask(__name__)
# MongoDBのセットアップ
client = pymongo.MongoClient("mongodb://111.1.1.1:11111/") #自分のアドレスを設定
db = client["attendance"]
collection = db["records"]
@app.route('/')
def index():
# MongoDBから出席記録を取得
attendance_records = list(collection.find())
# CSVから学生情報を読み込む
students_data = read_csv_file('./info.csv')
# TagIDをキーとして学生情報と出席記録を結合
for record in attendance_records:
student_info = next((item for item in students_data if item["TagID"] == record["tag_id"]), None)
if student_info:
record.update(student_info)
else:
record.update({'name': '-', 'number': '登録なし'})
# データをテンプレートに渡す
return render_template('index.html', data=attendance_records)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Attendance Records</title>
<style>
table {
border-collapse: collapse; /* セルの境界を結合 */
width: 100%; /* テーブルを親要素の幅いっぱいに広げる */
}
th, td {
padding: 8px; /* セル内の余白を設定 */
text-align: left; /* テキストを左寄せにする */
}
tr:nth-child(even) {
background-color: #f2f2f2; /* 偶数行の背景色を設定 */
}
</style>
</head>
<body>
<h1>Attendance Records</h1>
<table border="1">
<tr>
<th>number</th>
<th>name</th>
<th>tag_id</th>
<th>Timestamp</th>
</tr>
{% for record in data %}
<tr>
<td>{{ record.number }}</td>
<td>{{ record.name }}</td>
<td>{{ record.tag_id }}</td>
<td>{{ record.timestamp }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
以下のinfo.csvファイルでこのようなデータ(仮)を作成する.
name | number | TagID |
山田太郎 | 123456 | 0000000 |
鈴木花子 | 234567 | 123456789 |
佐藤一郎 | 345678 | abcdefg |