pypy.com/

Python、Unity、FX自動化などを勉強しています。あと、コーラと車も好きです。そこらへんについて、たまに記事を書きます。

Felica(ICカード)を使った勤退管理システムを作ってみた(Python3)

お久しぶりです。

今回はFelicaを使った勤退管理システムを作ってみたので、記事を書きます。

作ろうと思った理由

僕は今、大学院生なのですが、自分の研究室にはコアタイムなどはなく、
このままだと、だらけてしまいそうなので、研究時間が可視化できるようにしようと思いました。

Googleフォームなどで作ってマウスクリックでもよかったのですが、
マウスクリックだと飽きてやめてしまいそうなので、カードをタッチするだけでよい、
Felicaを使った管理システムを作ろうと考えました。

なので、勤退管理システムというよりは、自己管理するためのものといった感じです。

購入物

今回は、Felicaの読み取りを必要とするので、Felicaを読み取れるリーダーを購入しました。

僕が買ったものよりも新しいものもあるようですが、今回のような目的であれば、
古い方が安くてよいと思います。

買ったものは以下に貼っておくので、参考にしてください。

ドライバーのインストール

Felicaリーダーを購入したら、FelicaをPCのUSB端子に接続します。

その後、ドライバーをインストールします。

ドライバーは下記の場所からとって、実行して、インストールすればよいです。
Zadig - USB driver installation made easy

他の方の記事を読むと、libusbというものをインストールされている方が多いですが、
なくても動いたので、なくても良いのだと思います。

Pythonコード

今回は、Pythonで読み取りなどを実装します。

Felicaを扱うにあたって、nfcpyというライブラリをインストールします。

pip install nfcpy

nfcpyの使い方に関しては、公式のドキュメントを見ると大体わかるようになっています。
Getting started — nfcpy 1.0.3 documentation

今回は出勤と退勤時間をスプレッドシートに記録するような形での実装を目指して実装します。

まず、出勤用と退勤用のカードを用意して、それぞれのIDを調べます。

IDを調べるには、以下のようなコードを書けばよいです。

import nfc
def on_connect(tag):
    print(tag.identifier)
if __name__=="__main__":
    clf = nfc.ContactlessFrontend('usb')
    while clf.connect(rdwr={'on-connect': on_connect, 'targets': ['212F']}):
        print("connect")
    clf.close()

これで、自分のSuicaをタッチしてみると、以下のようなIDmであることが分かりました。

b'\x01\x14\x01\x14\xd4\x17:\x05'

これを基に出勤及び退勤用カードがタッチされた時の処理を書きます。

普通にif分とかで分岐しておけば良いです。

最終的には以下のようになりました。

スプレッドシートへの書き込みも行われていますが、その部分に関しては、
また今度記事を書きたいと思います。

import nfc
from nfc.clf import RemoteTarget
import datetime
from oauth2client.service_account import ServiceAccountCredentials
import gspread

pre_connect_time1 = datetime.datetime.now() - datetime.timedelta(days=1)
pre_connect_time2 = datetime.datetime.now() - datetime.timedelta(days=1)

def on_connect(tag):
    global pre_connect_time1,pre_connect_time2
    dt_now = datetime.datetime.now()
    dt1 = dt_now - pre_connect_time1
    dt2 = dt_now - pre_connect_time2
    if(tag.identifier==b'...自分のカードのIDmにすればよいです'):
        if(dt1.total_seconds()>60*30):
            pre_connect_time1 = dt_now
            print("出勤")
            write_spread_sheet(["出勤",dt_now.strftime('%Y-%m-%d %H:%M:%S')])
    elif(tag.identifier==b'...自分のカードのIDmにすればよいです'):
        if (dt2.total_seconds() > 60 * 30):
            pre_connect_time2 = dt_now
            print("退勤")
            write_spread_sheet(["退勤", dt_now.strftime('%Y-%m-%d %H:%M:%S')])
    else:
        print("カードが違います")

def write_spread_sheet(str_contents):
    scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
    credentials = ServiceAccountCredentials.from_json_keyfile_name('GCPのキーファイル', scope)
    gc = gspread.authorize(credentials)
    worksheet = gc.open_by_url(
        "スプレッドシートのURL").sheet1
    worksheet.append_row(str_contents)

if __name__=="__main__":
    clf = nfc.ContactlessFrontend('usb')
    while clf.connect(rdwr={'on-connect': on_connect, 'targets': ['212F']}):
        print("connect")
    clf.close()

実際にやってみた

研究室にFelicaリーダーを設置しました。
f:id:SaidaTaisei:20211122210450j:plain
PCに貼っただけですね。

これに登録したSuicaをタッチしてみます。
f:id:SaidaTaisei:20211122210520j:plain

f:id:SaidaTaisei:20211122210623p:plain

退勤ログが増えました。

今後はこのスプレッドシートのデータを見やすくしたいと思います。

今回はこれで終わります。