SESAMEスマートロックのAPIを使って、1ドア2ロックを1タップでコントロール

# 内容

1. 複数のSESAME(セサミ)スマートロックを、まとめて制御する手法です。
2. スマートフォン(Android/iPhone)やスマートウォッチ(Wear OS by Google(Android Wear)/Apple Watch)から、ウィジェットの1タップで制御できます。
3. Google Homeからも声で制御できます。

# 結果 (2020/6/10 追加)
解錠・施錠の様子を動画におさめました。
動作完了まで約15秒といったところでしょうか。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">SESAME 2ロックをまとめて解錠。 <a href="https://t.co/DYRHAxJ2LJ">pic.twitter.com/DYRHAxJ2LJ</a></p>&mdash; mm (@noirbreath) <a href="https://twitter.com/noirbreath/status/1270367737957638145?ref_src=twsrc%5Etfw">June 9, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">SESAME 2ロックをまとめて施錠。 <a href="https://t.co/Y2V40yWd9D">pic.twitter.com/Y2V40yWd9D</a></p>&mdash; mm (@noirbreath) <a href="https://twitter.com/noirbreath/status/1270368087506735106?ref_src=twsrc%5Etfw">June 9, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 背景
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">スマートロックは外部サービスと連携できてなんぼだよね。最初期から使ってきたQrioだけれど、SESAMEに置き換え予定。</p>&mdash; mm (@noirbreath) <a href="https://twitter.com/noirbreath/status/978874845705498630">2018年3月28日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

もうこの一言に尽きます。

Google Home MiniやNature Rimoで「スマートホーム」を体験し始め、「玄関の鍵も制御できたら」という思いが日増しに強くなっていました。
「OKグーグル、行ってきます」で解錠。帰ってきたら「OKグーグル、ただいま」で施錠。……スマートですよね？

当時、Qrio (SL1)とQrio Hubを設置して、外出先から操作できるようにしていましたが、APIの公開はナシ。Qrioのアプリからしか操作できません。また、わが家は1ドア2ロックなのですが、Qrio側で対応しているものの、シリアルに操作するため待ち時間が長く、不満な点でもありました。

そこで目についたのがSESAME。Wi-Fiアクセスポイントさえ追加すれば、外部からAPIを自由に叩けます。ロック本体とアクセスポイントが1対1なので2組必要と知って「え〜っ」となりましたが、これ裏を返せばQrioのようにシリアルに待たされることなく、パラレルに制御できるということになります。

Qrioの不満点をつぶせる！ということで早速購入。2ロック制御の開発を開始しました。

# 必要な知識、モノ、サービス

- **Google Apps Script**
    - SESAME APIを叩くために使用します。
    - スクリプトはGoogleドライブに設置します。
    - Googleアカウントを持っていれば、無料で使用可能です。
    - JavaScriptの知識ゼロの人でも何とかなりました。

- **IFTTT**
    - スマートフォンのウィジェットや、Google Homeの入力をきっかけに、Google Apps Scriptを叩くために使用します。
    - Button widget、Google AssistantとWebhookのサービスを使用します。
    - アカウントを取って使える状態にしてください。(手順など、ここでは触れません)

- **SESAME(セサミ)**
    - 今回制御する対象です。スマートロック本体とWi-Fiアクセスポイントが必要です。
    - ~~(近々発表される新型は、本体とアクセスポイントが多対1でもよくなるとか…)~~ → 多対1対応のアクセスポイントは、2019年春ごろ予定とのこと(2018年9月現在)
    - APIを使う場合、GoogleやFacebook連携ではなくメール/パスワードでアカウント登録したほうが吉です。
    - アプリ側で、クラウド連携の設定を忘れずに。
    - メーカー [ホームページ](https://jp.candyhouse.co) と [公式ブログ](https://ameblo.jp/candyhouse-inc)

# 参考文献

- [SESAME API (Version 1/Version 2) ドキュメント](https://docs.candyhouse.co/v1.html)
    - 最新のAPIは [Version 3](https://docs.candyhouse.co) です。
    - Version 1/Version 2 は廃止予定とのことなので、いずれ新しいAPIに書き直したいところ。

# 複数のSESAMEをまとめて制御する

## Google Apps Scriptの設置（基本部分）

APIを叩く基本部分を設置します。
手順は以下の通りです。

- ブラウザで [Google Drive](https://drive.google.com) にアクセスし、左上の「新規」をタップ。(スマートフォンの場合、ブラウザのPCモードで)

    ![Screenshot_2018-08-12-20-35-17.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/2b5cd9b4-584d-6d36-da38-a134b693f593.jpeg)

- 表示されたプルダウンメニューをたどって、「Google Apps Script」をタップ。(表示されない場合、その下の「アプリを追加」から追加)

    ![Screenshot_2018-08-13-07-45-56.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/3db5a576-2de4-4873-6f9d-4055359b2095.jpeg)

- プロジェクト名を入力(上段の赤枠)。コード欄(下段の赤枠)に元からある空の関数を削除し、代わりに後述の「コピペするスクリプト」をコピー＆ペースト。

    ![Screenshot_2018-08-13-07-53-02.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/4c75d787-0703-2f48-0043-f6bbb06dc0ee.jpeg)

    - コピペするスクリプト

        ```js
        // SESAMEのアカウント情報 (設定してください)
        var mail = '<メールアドレス>';
        var pass = '<パスワード>';
        
        // SESAME API の URL
        var apiUrl = 'https://api.candyhouse.co/v1';
        
        // SESAMEの名前とデバイスIDの保存用 (getSesameIdで設定する)
        var deviceId = {};
        
        // ログイン認証トークンの取得
        // (パスワード変更や30日経過で認証が切れるらしいので、当面は処理の最初に必ず呼び出すようにする)
        function getAuthToken() {
          var response = UrlFetchApp.fetch(apiUrl + '/accounts/login', {
            'headers': {
              'Content-Type' : 'application/json'
            },
            'method' : 'POST',
            'payload': JSON.stringify({
              'email'   : mail,
              'password': pass
            })
          });
        
          // トークンを抜き出して返す
          return(JSON.parse(response.getContentText()).authorization);
        }
        
        // アカウントに登録しているSESAMEの名前とデバイスIDの取得＆保存
        function getSesameId(authToken) {
          var response = UrlFetchApp.fetch(apiUrl + '/sesames', {
            'headers': {
              'X-Authorization' : authToken
            },
            'method' : 'GET'
          });
        
          // deviceId に保存する
          var array = JSON.parse(response.getContentText()).sesames;
          for(var i in array) {
            deviceId[array[i].nickname] = array[i].device_id;
          }
        }
        
        // 操作対象のSESAMEの名前と操作内容(lock/unlock)を指定して実行
        function controlSesame(authToken, name, control) {
          // APIを叩く間隔調整 (気になる人はコメントアウトを外して調整してください)
          //Utilities.sleep(3000);    // 3秒待ち
        
          var response = UrlFetchApp.fetch(apiUrl + '/sesames/' + deviceId[name] + '/control', {
            'headers': {
              'X-Authorization': authToken,
              'Content-Type'   : 'application/json'
            },
            'muteHttpExceptions': true,
            'method' : 'POST',
            'payload': JSON.stringify({
              'type' : control
            })
          });
        }
        
        // メイン処理
        function main(events) {
          // トークンの取得
          var authToken = getAuthToken();
          // SESAMEの名前とデバイスIDの取得
          getSesameId(authToken);
        
          // events から操作対象と内容を取り出して実行
          for(var i in events) {
            var name    = events[i].name;
            var control = events[i].type;
        
            // name が ALL の場合だけ特別
            if(name == 'ALL') {
              // アカウントに登録しているSESAMEすべてを一括処理
              // (1ドア2ロックの2個しか登録していない場合は ALL 指定で)
              for (var nameAll in deviceId) {
                controlSesame(authToken, nameAll, control);
              }
            } else {
              // SESAMEの名前を指定して個別に操作
              // (例えば玄関と勝手口など、まとめて解錠されたら困るようなところに設置している場合は名前指定で)
              controlSesame(authToken, name, control);
            }
          }
        }
        
        // IFTTTからのPOSTを受ける関数
        function doPost(e) {
          // IFTTTから渡された操作内容を取り出して main に丸投げ
          var events = JSON.parse(e.postData.contents).events;
          main(events);
        }
        ```

- スクリプト内にSESAMEのアカウント情報(<メールアドレス>と<パスワード>)を設定し、保存ボタンをタップ。

    ![Screenshot_2018-08-13-11-02-57.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/ee8ac55d-a071-800b-8d9b-aaf8b466b975.jpeg)

- 「公開」メニュー内の「ウェブアプリケーションとして導入」をタップ。

    ![Screenshot_2018-08-13-12-11-27.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/c84cfe1e-6ba3-4911-edcf-11a35f90aa87.jpeg)

- 「アプリケーションにアクセスできるユーザー」プルダウンメニューを「全員（匿名ユーザーを含む）」に変更し、「導入」をタップ。

    ![Screenshot_2018-08-13-12-16-06.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/3decb810-756f-45dc-ff12-24fe13dddf0c.jpeg)

- 承認の許可を行う。

    ![Screenshot_2018-08-13-12-18-28.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/5891605b-4c7f-e1b9-c9a6-9dece4afd87c.jpeg)

    ![Screenshot_2018-08-13-12-19-24.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/e18218b4-0545-6e00-fa45-efe8e6835cb3.jpeg)

- 「現在のウェブアプリケーションのURL」をコピーしてどこかにメモしたあと、「OK」をタップ。(このURLが、のちにIFTTTで指定するWebhookのURLになる)

    ![Screenshot_2018-08-13-12-22-44.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/866bf6bf-3b9e-84c2-03ec-34176b9351a2.jpeg)

以上で設置完了です。ブラウザは閉じても構いません。

## ウィジェットの1タップでSESAMEを制御

あとは、設置したGoogle Apps Scriptをどうやって叩くかだけです。
Webhookが使えるならば何でも構いませんが、ここではIFTTTを使います。
Button widgetを使って、スマートフォン(スマートウォッチ)のウィジェットのタップで操作できるようにします。

### :iphone: まずはスマートフォンの設定

IFTTTアプリで解錠のアプレットを作成します。

- IFTTTアプリの「My Applets」ボタン、「＋」ボタンをタップ。(下記画像の数字の順にタップ【以下同じ】)

    ![Screenshot_2018-08-13-17-03-05.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/c7512d11-0f7d-86d3-3d1a-cdf9ee55e79d.jpeg)

- 「this」をタップ後、"Search services"に"bu"まで入力すると候補が絞られるので、「Button widget」をタップ。Select trigger画面で「Button press」をタップ。

    ![Screenshot_2018-08-13-17-07-13.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/1f9c715f-7f45-1735-23cb-26feb84a0810.jpeg)

    ![Screenshot_2018-08-13-18-16-36.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/ef492e6d-c26b-9bf6-b732-634e820775a4.jpeg)

- 「that」をタップ後、"Search services"に"web"まで入力すると候補が絞られるので、「Webhooks」をタップ。Select action画面で「Make a web request」をタップ。Complete action画面で各種情報(後述)を入力後、「Create action」をタップ。

    ![Screenshot_2018-08-13-17-12-42.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/b07a60ad-7f20-1ad0-4335-d116b9fdb97d.jpeg)

    ![Screenshot_2018-08-13-17-57-08.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/55f6b839-2e2e-c3ab-107e-36e0203dceba.jpeg)

    - Complete action画面の入力内容

        |項目        |入力内容        |
        |:-----------|:---------------|
        |URL         |Google Apps Scriptの設置手順の最後にコピーした「現在のウェブアプリケーションのURL」|
        |Method      |POST            |
        |Content Type|application/json|
        |Body        |`{ "events": [{ "name" : "ALL", "type" : "unlock" }] }`|

        - 項目Bodyにはevents配列が指定できます。
        - events配列の各要素には、nameとtypeが指定できます。役割と指定可能な値は下記の通りです。

            |ITEM|役割|指定可能な値|
            |:---|:---|:-----------|
            |name|操作対象のSESAMEを指定する|ALL または SESAMEの名前|
            |type|操作内容を指定する|unlock または lock|

        - nameにALLを指定した場合、アカウントに登録しているSESAMEすべてを操作対象とします。
            - 1ドア2ロックの2個しか登録していない場合、ALLの指定で問題ありません。
        - nameにSESAMEの名前を指定した場合、指定されたSESAMEのみを操作対象とします。
            - 例えば玄関と勝手口など、まとめて解錠されたら困るようなところに設置している場合に使用します。
            - SESAMEの名前「玄関1」と「玄関2」を両方解錠したい場合、次のように指定してください。

                ```
                { "events": [{ "name" : "玄関1", "type" : "unlock" }, { "name" : "玄関2", "type" : "unlock" }] }
                ```

- 「Edit title」をタップしてタイトルを変更。最後に「Finish」をタップして完了。

    ![Screenshot_2018-08-13-17-21-18.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/835eedc0-d29b-1134-6b73-7385a65c268c.jpeg)

施錠のアプレットを作成する場合、上記解錠の手順から、Complete action画面の項目Bodyに指定したunlockをlockに変更するだけです。その他の手順は同じです。(タイトルは変えましょう)

スマートフォンへのウィジェットの設置は、Android/iPhoneそれぞれの作法に従ってください。

- (だいたいの) Androidは、ホーム画面の空白を長押ししてIFTTTウィジェットを追加する。(Small/Large)
- (iOS 11の) iPhoneは、ホーム画面を右にスワイプして、一番下の編集ボタンからIFTTTを追加する。

    ![Screenshot_2018-08-14-11-46-11.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/da29c29f-947e-ac28-6f13-1d8c33863d63.jpeg)

    - (表示されているタイトルがこれまでの例と違うのは、堪忍してください)

このウィジェットを1タップすることで、複数のSESAMEをまとめて操作(解錠／施錠)が可能になります。

### :clock4: スマートウォッチから使えるようにするには？

スマートウォッチのIFTTTアプリからも操作可能にします。

- Wear OS by Google (Android Wear)の場合
    - ウォッチ側にIFTTTアプリがインストールされていれば、特に準備は不要。
    - IFTTTアプリを起動するとウィジェットが表示されるので、上下にスワイプ(選択)してタップすると発動する。

        ![screen~01.png](https://qiita-image-store.s3.amazonaws.com/0/233188/90855f44-c4af-d52f-f44e-697c471ecf32.png)

- Apple Watchの場合
    - iPhone側のIFTTTアプリで「My Applets」ボタン、「歯車」ボタンをタップ。(下記画像の数字の順にタップ【以下同じ】)

        ![Screenshot_2018-08-14-13-29-19.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/ae0a4a27-f087-9916-fc67-bc53851981e9.jpeg)

    - 「Widgets」をタップ後、Widgets画面でApple Watchに表示させたい対象をタップ。

        ![Screenshot_2018-08-14-21-48-59.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/5b05a553-79ca-6608-a85a-28d3c191fb26.jpeg)

    - それぞれ対象の「Show on Apple Watch」スイッチをONにする。

        ![Screenshot_2018-08-14-13-24-02.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/94c2dcf0-8aa7-bf49-2a4b-10105dbe2ac8.jpeg)

    - Apple WatchのIFTTTアプリを起動するとウィジェットが表示されるので、デジタルクラウンを回転(選択)してタップすると発動する。

        ![IMG_1119.PNG](https://qiita-image-store.s3.amazonaws.com/0/233188/68f5d5be-f7c0-8bf2-5fc4-9e9c0328d9ba.png)

        - (セルラーモデルの場合、iPhoneとつながっていなくても実行可能なので便利)

## Google HomeでSESAMEを制御

先のIFTTTアプレット作成時は、「this」にButton widgetを使いましたが、Google Assistantを使うことでGoogle Homeから声で制御することも可能です。

ここでは、例として「ひらけごま」(解錠)のアプレットを作成します。

- IFTTTアプリの「My Applets」ボタン、「＋」ボタンをタップ。(下記画像の数字の順にタップ【以下同じ】)

    ![Screenshot_2018-08-13-17-03-05.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/c7512d11-0f7d-86d3-3d1a-cdf9ee55e79d.jpeg)

- 「this」をタップ後、"Search services"に"goo"まで入力すると候補が絞られるので、「Google Assistant」をタップ。

    ![Screenshot_2018-08-14-16-32-28.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/db655abc-d538-4193-c74e-9652bdd35411.jpeg)

- Select trigger画面で「Say a simple phrase」をタップ。Create trigger画面で下図の通り入力後、「Create trigger」をタップ。

    ![Screenshot_2018-08-14-16-36-52.jpg](https://qiita-image-store.s3.amazonaws.com/0/233188/7f87c3d9-ec69-4747-72ab-aea5257d6ea8.jpeg)

- 「that」の設定(Webhook)は、Button widgetを使った解錠アプレットと同じなので、そちらを参照してください。

これで、Google Homeに「OKグーグル、ひらけごま！」と言えば、まとめて解錠してくれるようになります。

# 最後に

SESAMEの製品自体にはいろいろツッコミどころがありますが、意外といい買い物をしたと思っています。

この記事は、数ヶ月前に作業したものを思い出しながら書きました。どこかに抜けや間違いがあるかもしれません。お気づきの点はご連絡ください。

で、数ヶ月前のことをどうして書く気になったかというと、急遽入院して暇になってしまったから。ベッドの上から動けなくても、Gemini PDAの変態USキーボードと戦いながら(書き終わる頃にやっと慣れた)、楽しく過ごせました。

~~心残りは、SESAMEの実機が手元にないため、動作の様子を動画に収められなかったことです。これはまた、退院してからの宿題にしたいと思います。~~
(2020/6/10) 記事の冒頭に動画を追加しました。2年越しの宿題を提出。動画自体は当時撮影していたのですが。きっかけをくださった @naoya-i 様、ありがとうございます。