NanoPi NEO2とICカードリーダーでタイムレコーダーを作る

NanoPi NEO2とICカードリーダーでタイムレコーダーを作る

この記事は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.sh
 1
 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で別サーバーに情報を送りそちらで記録することにする。

Felicaカード情報の送信側
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の制御が効かないのでコメント化する。

ウェブサーバー側(PHPが入っていること)
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 NEO2用に最新のarmbianをビルドして起動

追記: 2017年11月下旬にNanoPi NEO2はサポートボードに復活したのでイメージファイルはarmbian公式サイトからダウンロードできるようになっています。

2017年6月上旬以降にarmbianのNanoPi NEO2がハブンチョされたままになっている。NanoPi NEO2以外にもSoCにH5を搭載したボードやその他一部のボードも。NonoPi NEO(無印)は引き続き正式サポート。
正直なんでサポート外にされたのかよく理解していないが、NanoPi NEO2でarmbianが使えないというのは寂しい。(2017年6月上旬の古いイメージファイルは引き続き提供中)

そこで、今回はarmbianの最新のソースでNanoPi NEO2のOSイメージをビルドする。NanoPi NEO2以外のNanoPi NEO Plus2やOrangePi Prime, OrangePi PC2なども同様でいけると思う。(動作するかは未確認) 2017年8月3日追記: NanoPi NEO Plus2がdisabledにされた。

ビルド準備 (初回)

armbianのビルド環境構築についてはhttps://github.com/armbian/buildに解りやすく書いてある。
で、executionに書いてあるところまで実行する。

hoge@ubuntu:~$ apt-get -y install git
hoge@ubuntu:~$ git clone https://github.com/igorpecovnik/lib --depth 1
hoge@ubuntu:~$ cp lib/compile.sh ./  ←ここまで実行
hoge@ubuntu:~$ ./compile.sh           ←これは後で実行

2017年8月3日追記:
記事を書いた途端に変更になった。チッ

hoge@ubuntu:~$ apt-get -y install git
hoge@ubuntu:~$ git clone https://github.com/armbian/build
hoge@ubuntu:~$ cd build       ←ここまで実行
hoge@ubuntu:~/build$ ./compile.sh   ←これは後で実行

NanoPi NEO2(他H5搭載のボード等)はそのままではビルド対象として選択できない状態なのでビルド対象にしてやる。
2017年8月31日変更: 8月29日の変更によりこの手順は不要になった。

hoge@ubuntu:~$ cd ~/lib/config/boards
aw-som-a20.csc      hummingbird.csc     odroidc1.conf       orangepizero.conf
bananapi.conf       lamobo-r1.eos       odroidc2.conf       orangepizeroplus2-h3.conf
bananapim2.conf     lime2.conf          odroidxu4.conf      orangepizeroplus2-h5.wip
bananapim2plus.conf lime2-emmc.conf     olinux-som-a13.csc  pcduino2.conf
bananapim2ultra.csc lime-a10.eos        orangepi2.conf      pcduino3.conf
bananapim3.csc      lime-a33.conf       orangepi2g-iot.csc  pcduino3nano.conf
bananapipro.conf    lime.conf           orangepi.eos        pine64.conf
beelinkx2.conf      micro.conf          orangepilite.conf   pine64so.conf
clearfogbase.conf   miqi.conf           orangepimini.eos    pinebook-a64.conf
clearfogpro.conf    nanopiair.conf      orangepione.conf    roseapple.eos
cubieboard2.conf    nanopik2.wi         orangepipc2.wip     tinkerboard.conf
cubieboard4.csc     nanopim1.conf       orangepipc.conf     topwise-a721.csc
cubieboard.eos      nanopim1plus2.wip   orangepipcplus.conf udoo.conf
cubietruck.conf     nanopim1plus.conf   orangepiplus2e.conf udoo-neo.conf
cubox-i.conf        nanopineo2.wip      orangepiplus.conf
espressobin.wip     nanopineo.conf      orangepiprime.wip
guitar.eos          nanopineoplus2.wip  orangepiwin.wip
hoge@ubuntu:~$ ln -s nanopineo2.wip nanopineo2.conf
hoge@ubuntu:~$

2017年8月から ~/build/config/boards/に変更された。

要するに.wipなファイルのボードはビルド対象の選択メニューに表示されないので.confにしてやる。**.wipが更新されることもあるのでファイルコピーやリネームよりシンボリックリンクが良いかと。もちろんビルドしたいボードの.wipだけでいい。 2017年8月31日変更: 8月29日の変更によりこの手順は不要になったので取り消し線を付けた。

armbianでNanoPi NEO用をビルド1
画面1:
初めてarmbianをビルドする場合はcompile.shは初期値でいいと思う。何度かビルドして気に入らない部分だけ変更ということで。2017年8月3日追記: 8月に入ってからの変更で設定はconfファイルに記述するようになった。
すでにビルドしまくっている場合はタグを変更していることがあるかもなのでcompile.shのLIB_TAGを初期値(=空)に戻す。
なお、バージョンによっては項目名がLIB_TAGではないかも。(2017年7月29日現在の最新版ではLIB_TAG)

2017年8月31日追記: 8月29日の変更によりエキスパートモードでwipなボードをメニューから選択可能になった。compile.shを1度走らせるとconfig-default.confが作成されるのでそこに EXPERT="yes" を1行追加すると次回からエキスパートモードで実行される。または ./compile.sh EXPERT=yes で実行するか。

ビルド開始

hoge@ubuntu:~$ ./compile.sh
hoge@ubuntu:~/build$ ./compile.sh   ← ~/buildディレクトリで実行

初回はソースのダウンロード等でかなり時間がかかる。2回め以降の実行なら更新ファイルのダウンロードのみなのでそれほど時間はかからない。

armbianでNanoPi NEO用をビルド3
画面1:
2017年8月に入ってから追加された画面。
MicroSDカードに書き込むOSイメージファイルを作成するなら下側のFull OS image for flashingを選択する。

armbianでNanoPi NEO用をビルド2a
画面2a:
非エキスパートモードでは正式サポートのボードの選択画面が表示される。。カーソルキー上下でボードを選択してOK(Enter)で画面5へ。

armbianでNanoPi NEO用をビルド2b
画面2b:
エキスパートモードでも正式サポートのボードリストが表示されるが、リスト下中央に<Show CSC/WIP/EOS>という選択肢が増えている。それを選択して[Enter]

armbianでNanoPi NEO用をビルド3
画面3:
エキスパートモードであることの警告兼確認画面。 「理解して同意」(I understand and agree)を選択して[Enter]。

armbianでNanoPi NEO用をビルド4
画面4:
非正式対応のボードリストが表示されるので目的のボードを[↑][↓]で選択して[Enter]を押す。または選択して[Tab]を押して<OK>

armbianでNanoPi NEO用をビルド4
画面5a:
Debian JessieかUbuntu Xenialか好みで選択。ディストリビューションを選択して[OK]を選択。
画面6へ。

armbianでNanoPi NEO用をビルド4
画面5b:
エキスパートモードでは選択肢にDebian 9 Stretchが追加表示されるようになった。(8月末より)

armbianでNanoPi NEO用をビルド5
画面6:
暫く処理後にカーネルコンフィグが表示されるので必要に応じてオプションを指定。ワカンネって人はカーネルコンフィグのトップ画面(上の画面)でExitを選択して[Enter]。(これで標準値でビルド開始)
コンフィグ選択の階層を進んだ場合はその画面のExitで一つ上の階層に戻る。
基本的に解らんものは触らない。

ビルド環境のPCや選択したボード、カーネルコンフィグの内容によってビルド時間は大幅に変わるようだけど、とにかくだいぶ待たされてビルドがエラーにならずに完了したらOK.

完成したイメージファイルの取り出し

hoge@ubuntu:~$ cd output/images/
hoge@ubuntu:~$ ls
Armbian_5.32_Nanopineo2_Debian_jessie_dev_4.11.10.img
hoge@ubuntu:~$ ftp -p ftp.example.com      ←VirtualBoxからFTPの際はパッシブモードで
Connected to ftp.example.com.
220 ftp.example.com FTP server(Version 6.00LS) ready.
Name: hoge
331 Password required for hoge.
Password:
230 User hoge logged in, access restrictions apply.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> bi
200 Type set to I.
ftp> mput *img
mput Armbian_5.32_Nanopineo2_Debian_jessie_dev_4.11.10.img? y
227 Entering Passive Mode (ftp.example.com,203,115)
150 Opening BINARY mode data connection for 'Armbian_5.32_Nanopineo2_Debian_jessie_dev_4.11.10.img'.
226 Transfer complete.
1287651328 bytes sent in 10.67 secs 115.0516 MB/s)
ftp> quit
221 Goodbye.
hoge@ubuntu:~$ 

2017年8月から ~/build/output/images/に変更された。

上はFTPで別のPC(FTPサーバ)に出した例。
とにかく ~/output/images/ にビルドしたイメージファイルが作成されている筈。

イメージをmicroSDカードに書き込む

$ sudo dd if=./Armbian_5.32_Nanopineo2_Debian_jessie_dev_4.11.10.img of=/dev/sdb && sync

UNIX系のOSなら基本はこんな感じ。上の例だとMicroSDが/dev/sdbね。書き込み先を間違ったら泣くことになるので要確認。
こちらはストレージのマウント・アンマウントに慣れていないとまたは油断していると正常に書き込めないことも。

Windows, Linuxで簡単に確実にイメージを書き込みたいならarmbianでもオススメしてるっぽいEtcherを使う。
ダウンロードして実行するだけ。Windows用はインストール版とポータブル版があるので好みで選ぶとして、Linux用(通常)はダウンロードしたファイルを解凍して中のAppRunを実行するだけ。よほど特殊なディストリビューションでなければ動くかと。つまりとても簡単。

armbianでNanoPi NEO用をビルド6
画面6:
上はEtcherの画面。左の で書き込むイメージファイルを選択。中央の で書き込み先のMicroSDカードを指定(Etcher起動前に接続していれば自動で認識)、2つの選択が終わったら右の で書き込み開始。Etcherでは書き込み後のベリファイや自動アンマウントも行ってくれる。(これを変更する場合は右上の から)

Flash Complete!の表示が出たらEtcherを閉じる。microSDカードはそのまま抜いて大丈夫。

OS起動から電源断までの基礎

armbianでNanoPi NEO用をビルド7
画面7:
イメージ書き込み済みのmicoSDカードをNanoPi NEO2に差し込んで電源投入。30秒〜1分程度で起動する筈。
SSHでログイン。(IPアドレスの調べ方はこちら)
armbianの初期値は アカウントがroot、パスワードが1234。

初回ログイン後にrootアカウントのパスワード1234をもう一度入力、新しいrootアカウント用のパスワードを2回入力。
続いて一般ユーザーのアカウントを作成という流れ。
電源断はshutdown -P now [Enter] で緑のLEDが消えたら電源ケーブルを抜いてOK。

2017年8月3日追記: ビルドできるからって期待しちゃダメ。ハブンチョ前とカーネル変わって更に未完成度が高くなってる。あちこちおかしい所だらけ。(だから正式サポートから外れてるんだろうけど)

関連記事:
Up