ゎぃゎぃのおもちゃ箱

一般的な大学生の遊び場所

Suicaなどの交通系ICでバリスタ利用管理 SuiCafe ①

目的

予てから所属するラボにコーヒーバリスタを置きたいという話が持ち上がりました.ただ,コーヒー豆などのランニングコストを考え割り勘する等の幹事役が面倒で誰も手を出すことがありませんでした.
カフェイン中毒者の私は,この環境をなんとかしようと思い,コーヒーを飲んだ回数をデジタルで管理できるシステムを構築することにしました.
回数を記録するのにあたって,計算機に直接入力するパターンや,slackなどのチャットツールで記録する方法などが挙げられます.どれも利用者に負担がかかることもあり,ラボ内で定着しなさそうってのもあり,もっと簡単にできる方法を考えました.
それが,Suicaなどの交通系ICをタッチするだけで済むようなシステムです.

システムの考え方としてはとても簡単で似たようなことをしてる人も他所にたくさんいます.(入退室管理 suicaとかで検索)
この記事では,先駆者の功績を観ながら奮闘した結果を書いてゆきます.

FeliCaとは

ちょっとした前提知識を.
FeliCaNFCがごちゃまぜになっている人が多いですが,
NFCという規格に包含される1つの実装方式がFeliCaだと考えてください.
FeliCaNFCの違いは?という質問は,声優と田村ゆかりの違いは?と同じレベルってことですね.

FeliCaSonyが推進していて,公式で技術情報も拾えます.
Sony Japan | FeliCa | 法人のお客様 | ダウンロード
FeliCaについてもっと詳しく知りたければ,このページがおすすめです.
[PASMO] FeliCa から情報を吸い出してみる - FeliCaの仕様編 [Android][Kotlin] - Qiita

操作フロー

f:id:yy_kuso:20190116153522p:plain

  1. ユーザがコーヒーを飲みたいとき,FeliCaのリーダ「PaSoRi」にタッチ.
  2. FeliCaには,IDmと呼ばれるカード固有の文字列が割り振られており,これをシステム側でユーザと紐付けることでドリンク回数をカウント.PaSoRiをマシンから制御するために,pythonのnfcpyというライブラリを用いる.
  3. ドリンク回数をどこかに保存しておかないといけないので,Googleスプレッドシートにアップロード.(MySQL化は今度やる予定).FeliCaIDmエミュレータで偽装ができるので,生IDmデータをネットにあげるのはあまりよくないと思いこの辺についても考慮.

PaSoRiAmazonで3,000円くらいで買えます.
ソニー SONY 非接触ICカードリーダー/ライター PaSoRi RC-S380
24時間稼働させる予定なので,より省電力で安いマシンがほしいということで,
Raspberry Pi 3Bを購入しました.
Raspberry Pi3 Model B ボード&ケースセット 3ple Decker対応 (Clear)-Physical Computing Lab

製作準備

くそ長い前置きが終わったので,製作作業に入ります.

raspberry piに環境を構築

まずは,microSDにRaspbianを入れます.
Raspbianにはpythonが標準で入ってるはずなので,
リーダを制御するライブラリnfcpyを入れます.

$ sudo pip install nfcpy
$ pip list | grep nfcpy
nfcpy (0.13.5)

ちなみにこのライブラリ,python3系では動かないので注意.

次にサンプルコードを持ってきて動作テスト.

$ git clone https://github.com/nfcpy/nfcpy.git
$ cd nfcpy
$ lsusb
Bus 001 Device 004: ID 054c:06c3 Sony Corp. 
Bus 001 Device 005: ID 0424:7800 Standard Microsystems Corp. 
Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 002: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

このままだとsudoしないとPaSoRiが使えないので,以下のルールを追加.

$ sudo sh -c 'echo SUBSYSTEM==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"054c\", ATTRS{idProduct}==\"06c3\", GROUP=\"plugdev\" >> /etc/udev/rules.d/nfcdev.rules'

PaSoRiを抜き差し.tagtool.pyを実行.

$ ./examples/tagtool.py
No handlers could be found for logger "nfc.llcp.sec"
[nfc.clf] searching for reader on path usb
[nfc.clf] using SONY RC-S380/P NFC Port-100 v1.11 at usb:001:006
** waiting for a tag **     <<ここでiPhoneXsをタッチ>>
Type4ATag MIU=255 FWT=0.038664

とりあえず,なんか読み取れてるのはわかりました.
ただ,ここで詳しい人は感づいていると思いますが,これはiPhoneに登録してあるモバイルSuica(NFC type-f)ではなくNFC type-aを読み取っています.

このサンプルプログラムの仕様では,NFCのtypeを指定せずに最初にタッチされたNFCであればなんでも反応するようになっていると思います.(詳しく読んでないので怪しいですが)

Suicaを読み取れるようにする

最初からNFC type-fを狙い撃ちで待機するようにします.
以下のページのコードをもとに改造していくことにしました.
先駆者様ありがとうございます!
Raspberry PiにNFCリーダを接続してSuicaを読み取る - Qiita

# 212F(FeliCa)で設定
target_req_suica = nfc.clf.RemoteTarget("212F")
# 0003(Suica)
target_req_suica.sensf_req = bytearray.fromhex("0000030000")

となっているところが肝.

あとは効果音によるレスポンスやアップロードデータの暗号化なども実装して完成です.

実装内容

それぞれ先駆者様を参考にさせてもらいました.

まぁほとんどが既存コードを参考にしちゃってます.手っ取り早いので.

コード


各種,個人的なURLやコードは読み替えてください.

最後に

2ヶ月ちょい運用して思うのは,はやりGoogleスプレッドシートではなくMySQLとかでユーザ管理をしたほうがインテリジェントですし,slackとの連携も密にできるので,そこらへんどうにかしたいなということです.

ちなみになんでこんな"SuiCafe"とかいう名前にしたかというと
大空直美小澤亜李のsweet café time (通称:すいかふぇ)
から由来してます.