
この記事はNanoPi NEO2を使うということになってるけどNanoPi NEO2でなければならない要素はゼロで、Linuxが動く他のシングルボードコンピュータでもPCでも殆ど何でもOK。
事業所によくある従業員の出退勤を管理するためのタイムレコーダーと従業員各自用のタイムカード(消耗品)。よく考えると買うのが馬鹿らしいものの一つ。そこでNanoPi NEO2とICカードリーダー、そして従業員が持っているSuicaなどのFelicaカードを使ってタイムレコーダーを作る。ようするに事業所の入り口近くにICカードリーダーを置いといて、従業員が出勤時・退勤時に「ピッ」ってやるのを作る。集計は電子データを適当にゴニョゴニョするか何か作っちゃうか。とにかく好きにできるのが良いのよ。
とりあえずこのページでは使用するのはFelicaカードに限るとする。他のカードを入れると面倒だし。
今回はかなり古いSonyのFelicaカードリーダーS330をNanoPi NEO2とUSBで繋いだ。特にS330でなくてはならないということではない。どこのご家庭でも使われずに放置されてるICカードリーダーが1グロスほどあるかと思うのでテキトーなのを繋ぐ。2021年11月追記: どのカードリーダーでも使えるということではないみたい。また、使用するlibnfcのバージョンによっても利用できたりできなかったり動くようで変なエラーになったり。ハマると結構やっかいかも。
USBで繋いだ後にNanoPi NEO2側でdmesgの最後を見る。
[ 5645.339189] usb 8-1: new full-speed USB device number 2 using ohci-platform
接続したことが認識されたっぽい。
$ lsusb Bus 008 Device 002: ID 054c:02e1 Sony Corp. FeliCa S330 [PaSoRi] Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 004 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
USBのデバイスとしてS330カードリーダーが認識されている。システムにlsusbが入っていない場合はこの下でusbutilsをインストールするのでその後で再度確認して欲しい。
libnfcをインストール。 armbianなら以下3つだけでいい筈。
# apt install libnfc-bin libnfc5 libnfc-examples
nfc-pollを使いたいのでlibnfc-examplesも入れる。
FriendlyArmの公式で提供されているNanoPi NEO2用Ubuntu core 16.04を使用しているなら上の3つの他に以下も追加。
# apt install curl usbutils
カードリーダーを接続すると自動的にpn533_usb, pn533, nfcなどのモジュールがロードされることがある。これらは以下の動作テスト以降ずっと邪魔になる。ブラックリストに登録しておくのが無難だが、おそらく既に登録してくれている筈。/etc/modprobe.d/blacklist-libnfc.confが作成されていることを確認する。(ブラックリスト入りさせるモジュールが足りていないことがあるのでlsmodなどで確認して必要に応じて追加。lsmodでpn533_usbが表示されていてblacklist-libnfc.confに入っていないなら足りないということ。) 無ければ/etc/modprobe.d/blacklist-libnfc.confのようなファイルを自身で作成。blacklist nfcとblacklist pn533とblacklist pn533_usbの3行を書き込んで保存。システムを再起動するのがイヤで以下を実行するならmodprobe -r pn533_usbとmodprobe -r nfcとmodprobe -r pn533を実行。(lsmodでpn533_usbが表示されるならpn533_usbを最初に外す)
ICカードリーダー動作テスト
カードリーダーが使えるか確認
# nfc-scan-device -v
nfc-scan-device uses libnfc 1.7.1
1 NFC device(s) found:
- Sony / ?:
pn53x_usb:008:002
chip: PN533 v1.48
initator mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), ISO/IEC 14443-4B (106 kbps), Innovision Jewel (106 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps)
target mode modulations: ISO/IEC 14443A (106 kbps), FeliCa (424 kbps, 212 kbps), D.E.P. (424 kbps, 212 kbps, 106 kbps)
ICカードリーダーにカードを置かないで実行。
# nfc-list
nfc-list uses libnfc 1.7.1
NFC device: Sony / ? opened
情報らしい情報を返してこなかった。(正常)
SuicaでもPasmoでも何でもいいのでFelicaのカードをカードリーダーに置いた状態で実行。
$ nfc-list -v
nfc-list uses libnfc 1.7.1
NFC device: Sony / ? opened
0 ISO14443A passive target(s) found.
1 Felica (212 kbps) passive target(s) found:
FeliCa (212 kbps) target:
ID (NFCID2): 00 00 00 00 00 00 00 00
Parameter (PAD): 00 00 00 00 00 00 00 00
System Code (SC): 00 00
0 Felica (424 kbps) passive target(s) found.
0 ISO14443B passive target(s) found.
0 ISO14443B' passive target(s) found.
0 ISO14443B-2 ST SRx passive target(s) found.
0 ISO14443B-2 ASK CTx passive target(s) found.
0 Jewel passive target(s) found.
実際には00の部分は00〜ffが入っているがあえて全て00に置換している。
1 Felica (xxx kbps) passive target(s) foundと表示されると共にID, Parameter, System Codeが返ってきた。なお、カードの種類によって何が返ってくるかは違うみたい。
上3つの確認で Sony / ?: となっているが、?の部分は本来はデバイス名が入るところの筈。今回はどうでもいいので無視で。
nfc-pollも実行してみる。もしlibnfc.driver.pn53x_usb関係のエラーが出たとしても動いてれば(NFCID2が読めていたら)取り敢えず無視。
NanoPi NEO単独で記録の場合
simple_felica_recorder.sh1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/bin/sh
LOGFILE=/var/log/card.log
echo none > /sys/class/leds/nanopi:blue:status/trigger
while :
do
nid=$(nfc-poll | grep NFCID2 | cut -d: -f 2 | sed 's/ //g')
if ! [ x"$nid" = x ];then
echo `date '+%Y/%m/%d %H:%M:%S'` $nid >>$LOGFILE
echo heartbeat > /sys/class/leds/nanopi:blue:status/trigger
sleep 1
echo none > /sys/class/leds/nanopi:blue:status/trigger
sleep 1
fi
done
|
スクリプトはループで内容を実行。カードリーダーがFelicaカードを読んだ場合はその時刻とFelicaのNFCID2をログに書き出す。連続してカード情報を読み込むのを防ぐため2秒停止する。
読み取るのはNFCID2だけでPADとSCはこのページでは無視することにする。
nfc-listを使用するのもアリだが、読み取りが遅くなるのでカードをリーダーにかざして2秒ほど待つことになる。使い勝手が良くないしせっかくの高速なFelicaが生かされない。nfc-pollはカードを待ち受けてかざされたらすぐに反応するのでこちらを採用。
4, 11, 13行目、armbianの最新カーネルのNanoPi NEO2用はあちこち未完成なので/sys/class/leds/nanopi:blue:statusが存在しない(2017年7月30日現在)。/sys/class下に緑・青のLEDを制御できるディレクトリが存在しない状態なのでコメント化する。
$ chmod +x simple_felica_recorder.sh $ ./simple_felica_recorder.sh > /dev/null
スクリプトに実行権限を付けて実行。カードをかざしてみる。
ログには「日付 時刻 NFCID2」が1行ごとに記録されるのでCSVとして処理すればタイムレコーダー代わりにできる筈。「出勤」と「退勤」は無いけどシフト制勤務でもなければ要らないよね。
なお、上のように記録するだけだと不心得者がデタラメにカードをかざすと記録がノイズだらけになる。(不完全なカードIDが記録されるということではなく不要な記録が入るということ。)
NanoPi NEOからカードIDを別サーバに送信して記録する場合
問題はNanoPi NEO2のストレージが信頼性の欠片も無いmicroSDということ。もしもフラッシュメモリがぶっ壊れたら記録を取り出すことは絶望的で、タイムレコーダーとしては絶対にあってはならない。
そこで、カードの読み取りはNanoPi NEO2が行い、JSONで別サーバーに情報を送りそちらで記録することにする。
json_felica_recorder.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/sh
HOSTPATH=example.com/hoge/json_recv.php
LOGFILE=/var/log/card.log
echo none > /sys/class/leds/nanopi:blue:status/trigger
while :
do
nid=$(nfc-poll | grep NFCID2 | cut -d: -f 2 | sed 's/ //g')
if ! [ x"$nid" = x ];then
echo `date '+%Y/%m/%d %H:%M:%S'` $nid >>$LOGFILE
curl http://$HOSTPATH -X POST -H "Content-Type: application/json" -d '{"nid": "'$nid'"}'
echo heartbeat > /sys/class/leds/nanopi:blue:status/trigger
sleep 1
echo none > /sys/class/leds/nanopi:blue:status/trigger
sleep 1
fi
done
|
2行目と3行目を必要に応じて変更。
5, 14, 16行目はNanoPi NEO2のLEDの制御。カードを認識したら青LEDをピカピカさせる。上のスクリプトでも書いたが最新カーネルのarmbianとNanoPi NEO2の組み合わせではLEDの制御が効かないのでコメント化する。
json_recv.php
1 2 3 4 5 6 7 8 9 10 | <?php
$json_string = file_get_contents('php://input');
$data = json_decode($json_string);
$nid = $data->nid;
$file = '/var/log/card.log';
$current = file_get_contents($file);
$current .= date('Y/m/d H:i:s ') . $nid . "\n";
file_put_contents($file, $current);
?>
|
このjson_recv.phpはhttp://example.com/hoge/json_recv.phpでアクセスできるところに置く。
NanoPi NEOからJSON形式でPOSTされたカードIDを日時と共に/var/log/card.logに追記する。ただそれだけ。
実際にはログに書くのではなくデータベースに記録するとともにカードIDが登録済みであるか確認しカードの所有者名を返すとか前回の記録時間と比較して異常がないか(当日の出勤記録が無いとか前日の退勤記録が無いとか)を返すようにするのが良さげ。NanoPi NEO(json_felica_recorder.sh)側も返された値を読み上げるとか何かの合図の音を出すなどしてやらないと利用者(従業員)が不安になると思われる。逆にそのあたりをしっかりやれば出勤時専用・退勤時専用のリーダーを2つ用意する必要はないといえる。
関連記事:- アッチッチなNanoPi NEO3を冷やしたい パッド交換
- NanoPi NEO3冷却力強化後のUnixBench
- アッチッチなNanoPi NEO3を冷やしたい
- NTPサーバの時刻ソースに対するズレの調整
- NanoPi NEO3をv6プラスのルーターにする systemd-networkd + nftables
- NanoPi NEO3のUSB3.0ポートのネットワーク速度
- NanoPi NEO3でArmbian よきところでUnixBench
- NanoPi NEO3が届いた
- NanoPi NEOにRTCモジュールを付ける
- 新しい中華GPSモジュールとChronyで作るNTPサーバ (中編)
- 新しい中華GPSモジュールとChronyで作るNTPサーバ (前編)
- Prometheus2とGrafana6によるシステム監視 シングルボードコンピュータの温度表示
- NanoPi NEOでNTPサーバ再構築 (全まとめ)
- NanoPi NEO2をv6プラスのルーターにする 後編
- NanoPi NEO2をv6プラスのルーターにする 前編
- ELK Stackでシステム監視 FilebeatでNTP統計ログ取得 Logstashで加工
- NanoPi NEO2(arm64)用にFilebeatをビルド
- NanoPi NEO2を超コンパクトなアルミケースに入れる
- NanoPi NEO2用armbian 5.41 Debian 9 Stretch next 4.14.18
- NanoPi NEO2を100均の灰皿に入れてみた
- NanoPi NEO2のシステム監視 RPi-Monitorとnetdata
- NanoPi NEOとGPSモジュール用アルミケースを作る
- NanoPi NEO2 + DACで音楽プレーヤーVolumioを使う
- NanoPi NEO2にDACを接続
- NanoPi NEO2の最大クロック引き下げ後のUnixBench 再び
- NanoPi NEO2用armbian 5.32 Debian 9 Stretch 4.13.0-RC6
- NanoPi NEO2用armbian 5.32 Debian jessie 4.13.0-RC6
- NanoPi NEOをSIP電話機にする 後編 (その2)
- NanoPi NEO2とICカードリーダーでタイムレコーダーを作る(実用化編)
- NanoPi NEO2とICカードリーダーでタイムレコーダーを作る