お手軽にラズパイで勤怠管理システムを作ろう!

勤怠管理システムthumbnail

やぁみんな!ラミィ開発部のラミィだよ!

今日も開発をしていこう!

あらすじ

実はあたし、Youtubeだけでは生活できていないからパートのお仕事もしてるんだ。

でもそこでは出退勤を記録するような機械はないんだよね。残業や早退は自分で何分って出勤表に書いて月末に提出するの。

それじゃあいけない!ということで、上の人から大まかでも良いから時間をちゃんと書いて欲しいと頼まれているんだけど・・・出勤・休憩・退勤の時間を書いていくのって面倒じゃん?忘れるじゃん?

な・の・で!

ICチップが入っているカードをピッとかざして、簡単に時刻を記録するシステムを作って運用しようじゃないか!

でもあんまりお金を掛けるのも嫌なので、出来るだけ手元にあるものだけで作るよ!

材料

家の中を探して見つかったのが「Raspberry Pi(ラズベリー・パイ)」(初代)

Raspberry Pi本体

あとは何に使っていたのか分からないパソリもあったから、これだけでもう十分だね。

ICカードリーダーPaSoRi

画面もあると便利だと思うから、何故かあったラズパイ用2.8インチモニタも使おっか。

パソリ(RC-S370)をラズパイで使えるようにしよう

以下のサイトを参考にセットアップしていたんだけど、どうやっても無理だった・・・

🏷NFCリーダを制御する - ⭐

Raspberry Pi 3 Raspbian でUSB NFCリーダーライターを使ってみる

$ sudo python3 tagtool.py show
[nfc.clf] searching for reader on path usb
[nfc.clf.rcs956] input/output error while waiting for ack
[nfc.clf] no reader available on path usb
[main] no contactless reader found on usb
[main] no contactless reader available

というエラーが出続けて読み込めなかったんだ。

どうやらあたしが持っているカードリーダーの「RC-S370」っていうのがライブラリに対応していないみたいで、「RC-S380」はいけるみたいなんだよね。

たった10違うだけなのに・・・

でも新しく買い足すなんて嫌だから、どうにかRC-S370を使って読み込めるようにしたい!

色々と調べてみると、どうにか出来た人がいたので、それを参考にセットアップしたらちゃんと動いた!

PaSoRi RC-S330をRaspberryPiから使用する

でも、かなりめんどい!(汗)

こちらのサイトが消えてしまった場合に備えて、ここにも備忘録として書いとくね!

デバイスが認識されているかの確認

まず、lsusbコマンドでパソリが認識されているかどうか調べてみよう!

$ lsusb
Bus 001 Device 005: ID 054c:02e1 Sony Corp. FeliCa S330 [PaSoRi]
Bus 001 Device 004: ID 056e:1077 Elecom Co., Ltd ELECOM Trackball Keyboard
Bus 001 Device 003: ID 0424:ec00 Microchip Technology, Inc. (formerly SMSC) SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9512 Microchip Technology, Inc. (formerly SMSC) SMC9512/9514 USB Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

ちゃんと読み込まれてるね。もし読み込まれていなかったら、別なポートに挿してみるとか買い替えるかしてみてね。

libnfclibpafeをインストール

この2つをインストールすることで、FeliCaやNFCの情報を得られるようになるんだって。

libnfcのインストール

まずはlibnfcのインストールから!

$ sudo apt install libusb-dev
$ sudo apt install libpcsclite-dev
$ wget https://github.com/nfc-tools/libnfc/releases/download/libnfc-1.8.0/libnfc-1.8.0.tar.bz2
$ tar jxvf libnfc-1.8.0.tar.bz2
$ cd libnfc-1.8.0/
$ ./configure
$ make
$ sudo make install

ここまで終わったら、以下のファイルを編集するよ。

$ sudo nano /etc/modprobe.d/raspi-blacklist.conf

以下の2行を追加して保存しよう!

blacklist pn533
blacklist nfc

libpafeのインストール

$ wget http://hito.music.coocan.jp/pasori/libpafe-0.0.8.tar.gz
$ tar zxvf libpafe-0.0.8.tar.gz
$ cd libpafe-0.0.8/
$ ./configure
$ make
$ sudo make install

これで完了!

ライブラリ(SharedObject)のロード設定

ライブラリをインストールできたけど、まだパスを設定していないから実行しても動かないの。

その紐づけ作業をやれば、コマンドラインから実行できるようになるよ!

$ sudo nano /etc/ld.so.conf.d/usr-local-lib.conf

以下の1行を追加して保存しよう!

/usr/local/lib
# ライブラリパスの設定を再読み込み
$ sudo ldconfig -v
$ ldd /usr/local/bin/pasori_test
/usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so => /usr/lib/arm-linux-gnueabihf/libarmmem-v6l.so (0xb6f60000)
libpafe.so.0 => /usr/local/lib/libpafe.so.0 (0xb6f37000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6de3000)
libusb-0.1.so.4 => /lib/arm-linux-gnueabihf/libusb-0.1.so.4 (0xb6dc9000)
/lib/ld-linux-armhf.so.3 (0xb6f73000)

libpafe.so.0に情報が紐付けられていれば成功だよ。

あとはデバイスのテストと情報取得をやってみよう!

# デバイス認識のテスト
$ sudo pasori_test

# FeliCaカードの情報取得
$ sudo felica_dump

felicaテストのコマンド結果

参考にしたサイトではFeliCaの情報を取得していたけど、NFCの情報も取得できるみたい!

#NFC情報を取得するコマンド
$ nfc-poll
nfc-poll uses libnfc 1.8.0
error libnfc.chip.pn53x Unexpected PN53x reply!
NFC reader: Sony / RC-S370/P opened
NFC device will poll during 36000 ms (20 pollings of 300 ms for 6 modulations)
ISO/IEC 14443A (106 kbps) target:
ATQA (SENS_RES): 00 44
UID (NFCID1): 04 0f d1 73 73 00 00
SAK (SEL_RES): 00
Waiting for card removing...nfc_initiator_target_is_present: Target Released
done.

これでNFCタグを無駄にせずに済みそう(汗)

Pythonで出退勤システムを作る

読み取りの実行方法がコマンドラインからしか分からないから、pythonで実行する際にはsubprocessを使って、その結果を読み取るようにするよ。

まずはpythonからNFCタグを読み込むまで待機し続けるプログラムを作ってみよう!

import subprocess

print("Start read NFC")
while(True):
 cp = subprocess.run("nfc-poll", capture_output=True, text=True)
 data = cp.stdout
 if 'Waiting for card removing' in data:
  print(data)
  break

こんな感じだね。

これで、触れて→離したら結果を返してくれるよ。

$ python3 test_nfc.py
Start read NFC
nfc-poll uses libnfc 1.8.0
NFC reader: Sony / RC-S370/P opened
NFC device will poll during 36000 ms (20 pollings of 300 ms for 6 modulations)
ISO/IEC 14443A (106 kbps) target:
ATQA (SENS_RES): 00 44
UID (NFCID1): 04 ce 67 74 73 00 00
SAK (SEL_RES): 00
Waiting for card removing...done.

なんでそうなっちゃうかっていうと、触れたら「Waiting for card removing...」と出て、離すまでコマンドが実行され続けちゃって返ってこないんだよね(汗)

あたしはどうすればいいか分からないから、今回はこのまま行くよ!

そして出来たコードはこちら!

import subprocess
import datetime
import csv
import os

print("Start read NFC")
while(True):
    cp = subprocess.run("nfc-poll", capture_output=True, text=True)
    if 'Waiting for card removing' in cp.stdout:
        data = cp.stdout.splitlines()
        for m in data:
            if 'UID' in m:
                uid = m.replace(' ','')
                uid = uid[12:]
                now = datetime.datetime.now()

                #print(uid, now.strftime('%Y/%m/%d'), now.strftime('%H:%M:%S'))
                today = now.strftime('%Y/%m/%d')
                nowTime = now.strftime('%H:%M:%S')
                writer = []
                tmpFile = 'tmp/'+uid+'.tmp'
                if os.path.isfile(tmpFile):
                    with open(tmpFile) as f:
                        writer = f.read().replace('\n','').split(',')
                        if writer[0] == today:
                            writer.append(nowTime)
                        else:
                            saveFile = 'data/'+uid+'.csv'
                            with open(saveFile, 'a') as f1:
                                w = csv.writer(f1)
                                w.writerow(writer)
                            writer = [today, nowTime]
                else:
                    writer = [today, nowTime]

                print(uid + ': ',writer, '\n')
                with open(tmpFile, 'w') as f:
                    w = csv.writer(f)
                    w.writerow(writer)
                break

1日分の時刻をtmpファイルとして保存しておいて、次の出勤日にそのデータを出勤簿的なCSVファイルに保存するようにしてみたよ。

書き込む度にCSVファイルを展開して保存するのは嫌だなーと思ってこういう仕様にしてみたけどどうだろう。

もしラズパイが壊れたとしてもtmpファイルにデータがあるからきっと大丈夫!SDカードさえ壊れなければ!

CSVの代わりにDBに保存するような場合だと、もしかしたら1日分のデータを保存できないかもしれない。

そこは上手いこと何か工夫してもらえればなーって思うよ。

あとはこれを電源起動時に動くようにしてあげるだけだから簡単だね!

実践

職場に持っていって実際に使ってみたよ!

ラズパイで勤怠管理システム

職場のリソースはなるべく使わないようにして、モバイルバッテリーで起動させてる。

NFCカードを乗せて離すと、日時が追加されるのが分かるね!

ICカードリーダーにNFCタグを乗せる

ICカードリーダーからNFCタグを外す

勤怠管理システム実地テスト3

OK!これにて完成!

番外編:時刻合わせ

ラズパイにはRTC(リアルタイムクロック)という、システムの電源が入っていなくても時刻を刻み続けてくれる機能がないのね。

だからオンラインにして時刻を合わせるか、別途RTCモジュールを組み込まないといけない!

こんな感じの奴ね!

RTCモジュール

買ったは良いけど、ラズパイにディスプレイ付けちゃってるから付けられなかったのよね。

でも毎回家でラズパイを起動させて職場に持っていく、なんて面倒くさいからどうにか解決したい!

そこで、Wi-Fiモジュールを挿してスマホのテザリングで時刻を合わせれば良いんじゃないかなーって思いついたの!

で、USBのWi-Fiモジュールを買ってみたんだけど・・・適当なもの過ぎたのか全然反応しなかった(汗)

反応しないWi-Fiモジュール

(多分、本当なら中央付近のLEDみたいなのが光るはず・・・)

今のところ時刻合わせについては自宅で有線LANを繋いで合わせるしかない!残念!

終わりに

一応は動く物が出来たから、あたし的には満足!

だったんだけどぉ・・・

なんか、ごちゃごちゃいじくってたらラズパイが起動しなくなっちゃった(汗)

ACTのLEDがずっと赤点灯してるんだよね。

ACT赤点灯

とうとう壊れちゃったのかなーと意気消沈の面持ち。

たった2日だけ使ってラズパイによる勤怠管理システムは終了しましたとさ。

ちゃんちゃん