SonyのPaSoRi(RCS370)でSesameを動かす

# 背景
第2回「研究室のみんなそれぞれ1日使って何か作ろう！」の日。
他のメンバーの記事は[こちら](https://qiita.com/hayashi1989/items/1e8b534a579202466195)。
第1回の僕の記事は[こちら](https://qiita.com/Rtakaha/items/d07ef75d8c90d035fa3b)。

研究室の鍵にはSesameがついているんですが、開閉するたびに携帯でアプリ開いて操作するのが非常にめんどくさい。SuicaとかApple payのFelicaで開けられたらいいのに、と思った。

イメージ図はこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269742/ada18744-61d3-d69c-8629-eafd416aa3bb.png)

画像は[こちら](https://www.otwo.jp/blog/raspi_sesame_1/)の記事のものです。ありがとうございます。

#事前準備
https://www.otwo.jp/blog/raspi_sesame_1/
http://www.otwo.jp/blog/raspi_sesame_2/
この辺を参照。

- Raspberry Pi：研究室に転がってたやつ（多分Raspberry Pi3）。
- Sesame：研究室の入り口に設置済み。
- NFCリーダ：RCS370。研究室の先生の私物を拝借（なぜ持っているのか…）

# Raspberry Piでやってみた（失敗）
nfcpy: 1.0.3
python2: 2.7.16
python3: 3.7.3

[nfcpy](https://github.com/nfcpy/nfcpy)をpipでインストール。python3にも対応しているとのことだったのでpython3を使う方針。

```
$ pip3 install nfcpy
```

同時にgithubからソースをクローン。`examples/tagtool.py`を動かしてみる。

```
$ python3 tagtool.py
[nfc.clf] searching for reader on path usb
[nfc.clf] no reader available on path usb
[main] no contactless reader found on usb
[main] no contactless reader available
```
エラーが出る。

[公式ドキュメント](https://nfcpy.readthedocs.io/en/latest/examples/tagtool.html)とか、[Qiitaの記事](https://qiita.com/KASAMAKi/items/e8b54053414842a858c1)とかを調べてみると、デバイスIDを使ってUSBのパスを指定する必要があるみたい。
`lsusb`で調べてみると、

```
$ lsusb
(省略)
Bus 001 Device 025: ID 054c:02e1 Sony Corp. FeliCa S330 [PaSoRi]
(省略)
```

デバイスIDが表示されている。370ではなく330になっているのが気になるが、用いるドライバは同じみたいなのでよしとする。

USBパスを指定して実行してみる。

```
$ python3 tagtool.py
[nfc.clf] searching for reader on path usb:054c:02e1
[nfc.clf.rcs956] input/output error while waiting for ack
[main] no contactless reader available
```
あれれ？色々と調べてみると、指定したパスのデバイスとうまくコミュニケーションができていないみたい…。

# 色々試す
ピザ休憩を挟んで作業再開。
そもそも、RCS370 & Raspberry Pi & nfcpyでうまくいっている例がない。
[この記事](http://pongsuke.hatenablog.com/entry/2017/05/17/164317)を始め、370を380に変えたら動きました！系がちらほら…。

テンション下がりつつも、まだ諦めたくなかったのでMonsterを飲んで調査を続ける。

[この記事](https://hiro99ma.blogspot.com/2018/03/nfcdebian9rc-s370nfcpy.html)ではDebianとRCS370を使っている。`python -m nfc`でそもそもnfcpyがちゃんとインストールできているかを確認できるそう。とりあえずやってみる。

```
This is the 1.0.3 version of nfcpy run in Python 3.7.3
on Linux-4.19.57-v7+-armv7l-with-debian-10.0
I'm now searching your system for contactless devices
ERROR:nfc.clf.rcs956:input/output error while waiting for ack
I'm not trying serial devices because you haven't told me
-- add the option '--search-tty' to have me looking
-- but beware that this may break other serial devs
Sorry, but I couldn't find any contactless device
```
input/output errorと出ている。python, nfcpyのバージョンを参考記事と合わせても変わらなかった。

エラーの内容としては[この記事](https://sho-kun.com/?p=426)と同じ。うーん…。

nfcpy, pythonのバージョンを色々試しましたが、やっぱりできない…。これはお手上げ…。

# 僕なりの結論
RCS370 & Raspberry Pi & nfcpyはうまくいかない！

USBポートにRCS370が挿さったことをラズパイは認識するんだけどなあ…。まあRCS380使えということか。

# MacBook Airでやってみた（成功）
nfcpy: 1.0.3
python3: 3.6.5

それでも諦めたくなかったので、自分のパソコン（MacBook Air）でやってみることにした。

同様に[nfcpy](https://github.com/nfcpy/nfcpy)をクローンし、`examples/tagtool.py`を走らせる。

```
[nfc.clf] searching for reader on path usb
[nfc.clf] using Sony RC-S370/P RCS956v1.30 at usb:020:018
** waiting for a tag **
Type3Tag 'FeliCa Standard (RC-S???)' ID=カードのID (省略)
```
行けた。

# Sesameとの接続
[公式の記事](https://jp.candyhouse.co/blogs/how-to/suica%E3%81%A7%E3%82%BB%E3%82%B5%E3%83%9F%E3%82%92%E8%A7%A3%E9%8C%A0-with-%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A4)を参照。Python3を使いたかったのでところどころいじる。

```python:nfc_card.py
# -*- coding: utf-8 -*-
import requests
import json
import binascii
import nfc
import time
from threading import Thread, Timer

# login CANDY HOUSE account and get token
url = "https://api.candyhouse.co/v1/accounts/login"
head = {"Content-type": "application/json"}
payload = {"email":"アカウントのメールアドレス", "password":"アカウントのパスワード"}
response = requests.post(url, headers=head, data=json.dumps(payload))
token = response.json()["authorization"]

# Suica待ち受けの1サイクル秒
TIME_cycle = 1.0
# Suica待ち受けの反応インターバル秒
TIME_interval = 0.2
# タッチされてから次の待ち受けを開始するまで無効化する秒
TIME_wait = 3

# NFC接続リクエストのための準備
# 212F(FeliCa)で設定
target_req_suica = nfc.clf.RemoteTarget("212F")
# 0003(Suica)
target_req_suica.sensf_req = bytearray.fromhex("0000030000")

print('Waiting for SUICA...')
while True:
    # USBに接続されたNFCリーダに接続してインスタンス化
    clf = nfc.ContactlessFrontend('usb')
    # Suica待ち受け開始
    # clf.sense( [リモートターゲット], [検索回数], [検索の間隔] )
    target_res = clf.sense(target_req_suica, iterations=int(TIME_cycle//TIME_interval)+1 , interval=TIME_interval)

    if target_res is not None: # != -> is not に変更

        #tag = nfc.tag.tt3.Type3Tag(clf, target_res)
        #なんか仕様変わったっぽい？↓なら動いた
        tag = nfc.tag.activate_tt3(clf, target_res)
        tag.sys = 3

        #IDmを取り出す
        idm = binascii.hexlify(tag.idm)
        print('Suica detected. idm = ' + str(idm))

        if (idm == b'ICのID'):
            headers = {'X-Authorization':token,}
            response = requests.get('https://api.candyhouse.co/v1/sesames/セサミのシリアルナンバー', headers=headers)

            status = response.json()["is_unlocked"]

            url_control = "https://api.candyhouse.co/v1/sesames/セサミのシリアルナンバー/control"
            head_control = {"X-Authorization": token, "Content-type": "application/json"}

            # 開いてたら閉まる、閉まってたら開く
            if status:
                payload_control = {"type":"lock"}
            else:
                payload_control = {"type":"unlock"}

            response_control = requests.post(url_control, headers=head_control, data=json.dumps(payload_control))

            print(response_control.text)

        print('sleep ' + str(TIME_wait) + ' seconds')
        time.sleep(TIME_wait)
    #end if

    clf.close()

#end while
```
シリアルナンバーで、SESAME ID([これ](https://jp.candyhouse.co/blogs/how-to/api%E3%82%AD%E3%83%BC%E5%8F%96%E5%BE%97%E6%96%B9%E6%B3%95%E3%81%A8%E3%82%BB%E3%82%B5%E3%83%9Fid%E3%81%AE%E7%A2%BA%E8%AA%8D%E6%96%B9%E6%B3%95))ではないことに注意。ここをSESAME IDにしていたせいでAPIが叩けず、30分ぐらい無駄な時間を過ごした…。

# 使ってみる

- ドアの内側
![inside](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269742/837accd9-5ca6-0e94-878b-3e4de29d6c90.png)

笑
まあ、今回はしょうがない。

- ドアの外側
![outside](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269742/e2cc48b3-972f-62ce-0c0a-87cbb76f3791.jpeg)

NFCリーダを内側からセロテープではり（先生ごめんなさい）、外からICカードで開けられるか確認します。

…開く！けどタッチしてから３~５秒ほどの間がある。それでも
「携帯取り出す→ロック解除→セサミのアプリ開く→接続されるのを待つ→タップする」
よりは早いし楽！良さげ。

iPhone XにいれているモバイルSuicaもちゃんと反応。ただICカードと比べて若干反応が悪いかな？

# 感想と今後
さらっといけると思っていたけど、やっぱりさらっといかなかった。通信・ハードが絡むとちょっと難易度あがる。でも研究室がさらに便利になりそうで満足。

そしてRCS380を発注した。笑
すぐに届くみたいなので実装して扉につけます。380でうまくいったらまた記事にします。

月1回ぐらいでこの会やりたいなあ。次は何を作ろう。