スマートロックを自作してみた

# 概要
研究室の鍵をいちいち取り出すのが面倒なのでICカードで開けれるようにした話

# ゴール
ICカードをカードリーダにかざすと鍵の開閉ができるようになる

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">研究室の鍵ハックした<br>ICカード対応させた👍<br>めっちゃ楽になった笑笑 <a href="https://t.co/sb7WfswfD9">pic.twitter.com/sb7WfswfD9</a></p>&mdash; mori takuto(gump) (@m___04v) <a href="https://twitter.com/m___04v/status/1044184341134209024?ref_src=twsrc%5Etfw">2018年9月24日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# 用意するもの
- Raspberry Pi 
- サーボモーター
- カードリーダー
- (3dプリンタ)
- （Fusion360）



# システム構成
今回はサーボモーターを回転させるためのAPIを作成しています
そのためカードリーダーだけではなくスマホアプリ、スマートウォッチアプリからも開閉可能になっています
（APIが研究室のローカルで立っているためWiFiのパスがハックされない限り知らない人に開けられることはないです笑）

![スクリーンショット 2018-10-05 19.23.25.png](https://qiita-image-store.s3.amazonaws.com/0/192773/a33c99c6-372d-3563-7e9a-62ee051a2023.png)

- FlaskでAPIを立てエンドポイントを作成
- APIを叩いてサーボモーターをGPIOで制御

# この記事の内容

1.　FlaskでAPI作成
2.　3Dプリンタで鍵を回す部分の作成
3.　スマホアプリ作成
4.　実際にAPI叩いてみる
5.　固定台の作成
6.　カードリーダーの導入
7.　完成


## FlaskでAPI作成
今回はGPIOでサーボモータを制御したいのでPythonのFlaskを使用してAPIを作成しました

### Flaskのインストール

```
$ pip install flask
```

### 簡単なAPI作成

```python
from flask import Flask

app = Flask(__name__)

@app.route("/open")
def open():  
    return "open"

if __name__ == "__main__":
    # webサーバー立ち上げ
    app.run(host="192.168.**.**", port=5000)

```

### RPi.GPIOのインストール

```
$ pip install rpi.gpio
```

### サーボモータのセットアップ
今回はこの記事を参考にさせていただきました
*ピンの配置は少し変えています
[Raspberry Piでサーボモーターを回す](https://qiita.com/undo0530/items/51cc446eefec6c91c26d)

### GPIOでサーボモータを回す

```python
from flask import Flask

app = Flask(__name__)

@app.route("/open")
def open():  
    GPIO.setmode(GPIO.BCM)

    gp_out = 4
    GPIO.setup(gp_out, GPIO.OUT)

    servo = GPIO.PWM(gp_out, 50)
    servo.start(0)

    servo.ChangeDutyCycle(7.5)
    time.sleep(0.5)

    servo.stop()
    GPIO.cleanup()    
    return "open"


if __name__ == "__main__":
    # webサーバー立ち上げ
    app.run(host="192.168.**.**", port=5000)
```

## 3dプリンタで鍵を回す部分の作成
サーボモータの先っちょに鍵をはめる部分をつけたいのでFusion360でモデリングしてプリントします
![スクリーンショット 2018-10-05 19.51.28.png](https://qiita-image-store.s3.amazonaws.com/0/192773/f69554c0-ed1a-ea4a-d00d-5c55bac8654e.png)
完成したらサーボモーターの先っちょにホットボンドなどでくっつけます


## スマホアプリ作成
今回はAndroidのスマホとAndroid Wearのアプリを作成します
適当にボタンを配置してAPIを叩いてみます

```kotlin

openButton.setOnClickListener {
    object: MyAsyncTask2() {
        override fun doInBackground(vararg params: Void): JSONArray? {
            var result : JSONArray? = null
            var res: String = ""
            try {
                res = Run().run("http://192.168.**.**:5000/open")
                val resJson = JSONArray(res)
                status.text = "Status: Open"
                result = resJson
            } catch (e: IOException) {
                e.printStackTrace()
            } catch (e: JSONException) {
                e.printStackTrace()
            }
            return result
        }
    }.execute()
}
```

## 実際にAPI叩いてみる
ここまでで鍵が回せるか試してみます
意外と回るんですね笑

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">スマートウォッチで鍵が開けれちゃうよ✌️ <a href="https://t.co/QS6HL2651j">pic.twitter.com/QS6HL2651j</a></p>&mdash; mori takuto(gump) (@m___04v) <a href="https://twitter.com/m___04v/status/1043041624605908992?ref_src=twsrc%5Etfw">2018年9月21日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## 固定台の作成
上の動画では手で押さえているので固定する台を作成します

![スクリーンショット 2018-10-05 19.54.25.png](https://qiita-image-store.s3.amazonaws.com/0/192773/06229310-90cd-81ed-08ed-6d3835d44c06.png)

こんな感じで作成してプリント

### 設置
固定台を設置すると手で押さえなくても回るようになりました！
こんな感じでゴリ押しです笑

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">裏側のゴリ押し具合 <a href="https://t.co/8gnCfgu8Vm">pic.twitter.com/8gnCfgu8Vm</a></p>&mdash; mori takuto(gump) (@m___04v) <a href="https://twitter.com/m___04v/status/1044185295019696128?ref_src=twsrc%5Etfw">2018年9月24日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## カードリーダーの導入
RaspiでのNFCカードリーダの利用はこの記事を参考にさせていただきました
[Raspberry PiにNFCリーダを接続してSuicaを読み取る](https://qiita.com/undo0530/items/89540a03252e2d8f291b)

この記事を参考に少しコードを修正します
今回はSQLite3にカード情報を事前に登録して、登録したカードのみで開閉できるようにしました
また、ボタンを設置して、開けるモード、閉めるモードを切り替えるようにしましたが記事が長くなりそうなので割愛します
基本的にはただのLチカなので、この記事をみてもらえるとありがたいです

[ラズパイと音声認識でLチカ](https://qiita.com/mr_04v/items/6a16663ce9a80b2e2b92)

```python
target_req_suica = nfc.clf.RemoteTarget("212F")

while True:
    clf = nfc.ContactlessFrontend('usb')
    target_res = clf.sense(target_req_suica,iterations=int(TIME_cycle//TIME_interval)+1 , interval=TIME_interval)

    if target_res != None:
        tag = nfc.tag.activate_tt3(clf, target_res)
        tag.sys = 3

        #IDmを取り出す
        idm = binascii.hexlify(tag.idm)
        
        #sqlite使って登録判定
        cur = conn.cursor().execute('select count(*) from cards where card_id = ?',(idm,))
        
        isExist = False
        if cur.fetchone()[0] > 0:
          isExist = True
      
        output=""

        if isExist == True:
            output= not GPIO.input(2)
            if output == True: 
                requests.get(open_url)
            else:
                requests.get(close_url)
```


## 完成

大分コード省略してますが完成です
これでいちいち鍵を取り出す必要がなくなりました！
スマートウォッチでも開けれるので楽チンですね！！！
家にも導入しようかな。。。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">研究室の鍵ハックした<br>ICカード対応させた👍<br>めっちゃ楽になった笑笑 <a href="https://t.co/sb7WfswfD9">pic.twitter.com/sb7WfswfD9</a></p>&mdash; mori takuto(gump) (@m___04v) <a href="https://twitter.com/m___04v/status/1044184341134209024?ref_src=twsrc%5Etfw">2018年9月24日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#参考記事
[Raspberry Piでサーボモーターを回す](https://qiita.com/undo0530/items/51cc446eefec6c91c26d)
[Raspberry PiにNFCリーダを接続してSuicaを読み取る](https://qiita.com/undo0530/items/89540a03252e2d8f291b)
[ラズパイと音声認識でLチカ](https://qiita.com/mr_04v/items/6a16663ce9a80b2e2b92)