Suicaなどの交通系ICでバリスタ利用管理 SuiCafe ①
目的
予てから所属するラボにコーヒーバリスタを置きたいという話が持ち上がりました.ただ,コーヒー豆などのランニングコストを考え割り勘する等の幹事役が面倒で誰も手を出すことがありませんでした.
カフェイン中毒者の私は,この環境をなんとかしようと思い,コーヒーを飲んだ回数をデジタルで管理できるシステムを構築することにしました.
回数を記録するのにあたって,計算機に直接入力するパターンや,slackなどのチャットツールで記録する方法などが挙げられます.どれも利用者に負担がかかることもあり,ラボ内で定着しなさそうってのもあり,もっと簡単にできる方法を考えました.
それが,Suicaなどの交通系ICをタッチするだけで済むようなシステムです.
システムの考え方としてはとても簡単で似たようなことをしてる人も他所にたくさんいます.(入退室管理 suicaとかで検索)
この記事では,先駆者の功績を観ながら奮闘した結果を書いてゆきます.
FeliCaとは
ちょっとした前提知識を.
FeliCaとNFCがごちゃまぜになっている人が多いですが,
NFCという規格に包含される1つの実装方式がFeliCaだと考えてください.
FeliCaとNFCの違いは?という質問は,声優と田村ゆかりの違いは?と同じレベルってことですね.
FeliCaはSonyが推進していて,公式で技術情報も拾えます.
Sony Japan | FeliCa | 法人のお客様 | ダウンロード
FeliCaについてもっと詳しく知りたければ,このページがおすすめです.
[PASMO] FeliCa から情報を吸い出してみる - FeliCaの仕様編 [Android][Kotlin] - Qiita
操作フロー
- ユーザがコーヒーを飲みたいとき,FeliCaのリーダ「PaSoRi」にタッチ.
- FeliCaには,IDmと呼ばれるカード固有の文字列が割り振られており,これをシステム側でユーザと紐付けることでドリンク回数をカウント.PaSoRiをマシンから制御するために,pythonのnfcpyというライブラリを用いる.
- ドリンク回数をどこかに保存しておかないといけないので,Googleスプレッドシートにアップロード.(MySQL化は今度やる予定).FeliCaのIDmはエミュレータで偽装ができるので,生IDmデータをネットにあげるのはあまりよくないと思いこの辺についても考慮.
PaSoRiはAmazonで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")
となっているところが肝.
あとは効果音によるレスポンスやアップロードデータの暗号化なども実装して完成です.
実装内容
それぞれ先駆者様を参考にさせてもらいました.
- 読み取ったIDmをAES暗号化(【Python】pycryptoで投げるたけでAES暗号化復号してくれる関数作った。 - Qiita)
- 効果音を出す(.wav)(Raspberry Piで音楽(wav/mp3)ファイルを再生する方法 python編 - Qiita)
- 音量を上げる(RaspberryPi 3 コマンドで音量を上げる(ラジオをテレビで再生→音量不足→コマンドで音量UP) - min117の日記)
- 音関連で実行時に出力されるwarningをどうにかする(espeak TTS ALSA Unknown PCM cards - Raspberry Pi Forums)
- Google Cloud Platformの利用(これから始めるGCP(GCE) 安全に無料枠を使い倒せ - Qiita)
- Googleスプレッドシートにデータを追加(PythonでGoogleスプレッドシートを編集 - Qiita)
- slackに通知
- systemdでpythonプログラムを自動起動
まぁほとんどが既存コードを参考にしちゃってます.手っ取り早いので.
コード
各種,個人的なURLやコードは読み替えてください.