ラズベリーパイとセサミ３とUSBカメラボタンで鍵を開ける

# ラズベリーパイとセサミ３とUSBカメラボタンで鍵を開ける

100円ショップで買ったBluetoothボタンで、近くでボタンを押したときに、セサミの鍵を開ける方法を記述しています。
子供に家の鍵として渡していましたが、テレワークのため、私が家にいるので使わなくなりましたが、、、

## 利用環境

* Raspberry Pi 2 Model B (古く使わないものを今回使用)
    * ubuntu(ラズパイOsだとうまくWifi、Bluetoothがつながらずubuntuにしました。)
    * Wifiモジュール
    * Bluetoothモジュール
* 100円ショップで売られていた、300円のカメラシャッターボタン
* セサミ3 & Wifiモジュール

## 手順

1. Bluetoothでペアリング
2. セサミのAPI使用
3. Pythonの設定
4. 自動起動

## Bluetoothでペアリング

シャッターボタンとラズパイとの接続設定を行います。

* ```bluetoothctl``` でペアリングを行います。
* インストールしていない場合はインストールしましょう。
* ```bluetoothctl```のコマンド```scan on```でデバイスを探します。シャッターボタン側はボタンを押します。
* ```bluetoothctl```のコマンド```pair xx:xx:xx:xx:xx:xx```でデバイスとペアリングを行います。
* ```bluetoothctl```のコマンド```trust xx:xx:xx:xx:xx:xx```でデバイスを信頼し、自動でペアリングできるようにします。
* その時のIDをメモしておきます。

手順に難しいところはありません、そもそもBluetoothがラズパイで使用できれば問題ありません。
私の使用しているRaspberry Pi 2 Model BはWifiもBluetoothもないので、そこからでした。

## セサミのAPI使用

* 今回使用するセサミの鍵をアプリから作成します。QRコードで作成しその内容をAPIで利用します。
    * https://sesame-qr-reader.vercel.app/
        * 下記のuuidとsecret_keyを設定します
* Web API(インターネットを通じてセサミを操作する)を呼ぶためにAPIキーを取得します。
    * 下記のapi_keyを設定します
* 参考 https://doc.candyhouse.co/ja/SesameAPI

QRコードからsecret_keyを取るところが迷いました。ドキュメントに書いてある通りに手作業で抜き出したら、うまう抜き出せず、サイトを使用しました。

## Pythonの設定

下記コマンドでPythonのモジュールをインストールします。

* ```python -m pip install requests```
    * https://docs.python-requests.org/en/latest/user/install/#install
* ```python -m pip install evdev```
    * https://python-evdev.readthedocs.io/en/latest/
* ```python -m pip install pycryptodome```
    * https://pycryptodome.readthedocs.io/en/latest/src/introduction.html
 
下記ファイルのuuid、secret_key 、api_key を上記で取得した値に置き換えます。

```/opt/sesame/sesame.py```

```
import base64
import datetime
import json
import time
import traceback

import evdev
import requests
from Crypto.Cipher import AES
from Crypto.Hash import CMAC


device_id = '00:00:00:00:00:00'

uuid = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
secret_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
api_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
cmd = 83  # 88/82/83 = toggle/lock/unlock


def unlock(history):
    base64_history = base64.b64encode(bytes(history, 'utf-8')).decode()
    print(base64_history)
    headers = {'x-api-key': api_key}

    ts = int(datetime.datetime.now().timestamp())
    messageb = ts.to_bytes(4, byteorder='little')
    message = messageb.hex()[2:8]
    cmac = CMAC.new(bytes.fromhex(secret_key), ciphermod=AES)

    cmac.update(bytes.fromhex(message))
    sign = cmac.hexdigest()
    # 鍵の操作
    url = f'https://app.candyhouse.co/api/sesame2/{uuid}/cmd'
    body = {
        'cmd': cmd,
        'history': base64_history,
        'sign': sign
    }
    print(body)

    res = requests.post(url, json.dumps(body), headers=headers)
    print(res.status_code, res.text)


def main():
    while True:
        try:
            paths = [path for path in evdev.list_devices()]
            paths.sort()
            devices = [evdev.InputDevice(path) for path in paths]
            for device in devices:
                # print(device)
                # ls /dev/input でevent番号要確認
                if device.phys == device_id:
                    print('find divice')
                    print(device)

                    for event in device.read_loop():
                        # print(event)
                        if event.type == evdev.ecodes.EV_KEY:
                            if event.value == 1:  # 0:KEYUP, 1:KEYDOWN
                                print(event.code)

                                if event.code == evdev.ecodes.KEY_VOLUMEUP:
                                    print('unlock open')
                                    unlock(device.phys)

                                if event.code == evdev.ecodes.KEY_ENTER:
                                    print('ENT')
                    print('loop end')
        except Exception as e:
            # print(traceback.format_exc())
            print('Retry...')
            print(e)

        time.sleep(1)


if __name__ == '__main__':
    main()
```


### シャッターボタンが複数の場合は、
```
device_id = [ 'xx:xx:xx:xx:xx:xx','xx:xx:xx:xx:xx:xx']
```
のように複数にし、
```
                if device.phys == device_id:
を
                if device.phys in device_id:
```
にすればいいと思います。


## 自動起動

```/etc/systemd/system/sesame.service```を下記内容で作成します。


```
[Unit]
Description = sesame open lock

[Service]
ExecStart = sudo -E /usr/bin/python3 /opt/sesame/sesame.py >> /opt/sesame/log.log
Restart = always
Type = simple
User=ubuntu
Group=ubuntu

[Install]
WantedBy = multi-user.target

```
 
下記コマンドで開始と有効化を行います。

```
sudo systemctl start sesame
sudo systemctl enable sesame

```