スマートロック SESAME(セサミ) のAPIをGoogle Apps Scriptから簡単に利用する方法(施錠・解錠のほかWebhookを使用したログ記録など)

このエントリーをはてなブックマークに追加

1年ぶりの記事です。 前回書いた記事をすっかり忘れてしまっていたので、ぜひともどなたかCloud Brainの開発をお願いしたいと思います。

さてさてわたしの運営していますコワーキングスペース茅場町 Co-Edoでは、複数のスマートロックを利用しています。 そのうちのひとつが SESAME(セサミ) という CANDY HOUSE, Inc. の製品です。 (早朝の利用時などもある セミナールーム茅場町 Co-Edo 3F 貸会議室 にて利用しています)

SESAMEの良いところは APIを使用し自分にあった使い方を構築できる ところ。 これまで導入してからまったくAPIを活用してなかったのですが、Google Apps Script単体でAPIを使用したりWebhookを受けてログ記録等をしたりできることに(遅まきながら)気づいたので開発してみました。

わたしはSESAME miniではなく旧製品を使用していますが、どちらであっても同じようにAPIを利用可能です。
旧製品ユーザーにも優しくて嬉しい。

docs.candyhouse.co

開発したのはこちら。

  • Google Apps Script で簡単にAPIを扱うためのライブラリ
  • 受付の iPad のホーム画面のアイコン(🔒と🔓)をタップし施錠と解錠をするショートカット
  • SESAMEの施錠・解錠の状態変更時のWebhookを利用しGoogleスプレッドシートにログを自動記録するGoogle Apps Script

今回の記事では、今後SESAMEAPIを利用して開発したいと考えている方に向けて、どのように開発するかをお伝えしたいと思います。

以下、順番を一部変え、APIの利用方法から説明していきます。 (さくっと使いたい人は途中で読み終えて構いません)

iPadiPhone) から施錠・解錠するショートカットを作成し遠隔操作する方法

iOSにはショートカットという複数の操作を自動化するための機能(アプリ)が備わっています。 SESAMEAPIを利用する際にはGETやPOSTができれば良いため、ショートカットを使ってAPIを使用することも可能です。

大まかな手順としては ①API利用の準備(API Keyの確認) ②デバイスIDの確認 ③ショートカットの作成 となります。

API利用の準備(API Keyの確認)

当然ながらAPIを使用し操作ができるのは所有しているデバイスSESAME)のみです。 自分のアカウントに紐付いたデバイスを操作するための情報 API Key が必要になります。

CANDY HOUSE Dashboard にアクセスします。

普段使っている人は多くないかもしれませんが、このダッシュボードにはセサミの設置場所が地図になっていたり、使用状況がグラフで確認できたりということが可能です。

左側のメニューに「API設定」というのがありますのでクリックすると再度の認証が必要となります。 「コードを送信する」をクリックし送られてくるメールに記載された検証コードを入力すると「API Settings」のページが表示されます。 (このページを閉じるとあらためて同様の認証が必要になりますので、うかつに遷移しないように注意しましょう)

ここで取得する API Key を利用すると、誰でも自由にSESAMEを操作できるようになります。 取り扱いには充分に注意し、誰でも目に触れる場所で表示されることのないようにしてください。

[ADD]ボタンをクリックすると、あらたに API Key が生成されます。 画面に表示されるのは、この一度きりですので、忘れずにクリップボードにコピーし、自分だけが確認できる場所に記録しておきましょう。

忘れてしまった場合は、削除した上で、あらたに作成すれば大丈夫です。 その時点で旧API Keyは使用できなくなりますので、すでに利用している場合は削除する必要はありません。

バイスIDの確認(APIの基本的な使い方)

SESAMEAPIドキュメントはとても分かりやすくできています。 ターミナルから試しに利用する場合の手順も書いてありますので、そのとおりに実行してみましょう。

Macの方は ターミナル で、Windowsの方も Windows Terminal などを利用して実行できます

アカウントに紐付いたすべてのデバイスの一覧をJSONで取得(GET)するコマンドを使用します。

2020/07/01 現在のAPIバージョンは 3 で、API利用時のエンドポイントは次のとおりです。

https://api.candyhouse.co/public

これに続けてデバイス一覧を取得する次のコマンドを利用します。

/sesames

くっつけるとこんな感じです(GETで取得)

https://api.candyhouse.co/public/sesames

APIの扱いに慣れてない方も、以下同じように可能です。GETじゃなくてPOSTする場合もあります。

Authorizationヘッダーにさきほど取得した API Key をつけて送信します。 (YOUR_AUTH_TOKEN を書き換えてください)

curl -H "Authorization: YOUR_AUTH_TOKEN"  https://api.candyhouse.co/public/sesames

次のように、配列で返されます(下記の例では2つのデバイスが同じアカウントで使用されていることになります)

  [
    {
      "device_id": "00000000-0000-0000-0000-000000000000",
      "serial": "ABC1234567",
      "nickname": "Front door"
    }, {
      "device_id": "00000000-0000-0000-0000-000000000001",
      "serial": "DEF7654321",
      "nickname": "Back door"
    }
  ]

この device_id が分かればOKです。

基本的なAPIの使い方を説明いたしますが、読み飛ばしていただいても構いません。 たとえば次のように使用します。

/sesame/{device_id}

ふたたび curl コマンドで バイスの状態の確認 をしてみましょう。

curl -H "Authorization: YOUR_AUTH_TOKEN" https://api.candyhouse.co/public/sesame/00000000-0000-0000-0000-000000000001

次のような結果が返されます。

  {
    "locked": true,
    "battery": 100,
    "responsive": true
  }

施錠・解錠などの操作 をする場合は、POSTをします。

curl -H "Authorization: YOUR_AUTH_TOKEN" -H "Content-Type: application/json" -X POST -d '{"command":"lock"}' https://api.candyhouse.co/public/sesame/00000000-0000-0000-0000-000000000001

POSTしているデータはJSONを文字列化(stringify)したものです。 lock unlock sync の3つのコマンドがあります。

sync はサーバー上のステータスを同期させるために利用するようですが、使いすぎるとバッテリーを消費するという注意書きがありました。

task_id というものが返されます。 スマートロックは lock というのコマンドをPOSTした直後は、まだ成功したかどうかを確認することができません。 時間をおいてから task_id を使って結果を取得する必要があります。

  {
    "task_id": "01234567-890a-bcde-f012-34567890abcd"
  }

実行結果の取得 は、次のようにGETできます。

curl -H "Authorization: YOUR_AUTH_TOKEN" https://api.candyhouse.co/public/action-result?task_id=01234567-890a-bcde-f012-34567890abcd

次のように返ってきます。 もし statusprocessing だった場合は、もう少し時間をおく必要があります。

  {
    "status": "terminated",
    "successful": true
  }

ショートカットの作成

上述のとおり、施錠・解錠を行うには、APIのエンドポイントに対し、デバイスIDを指定したうえで lock/unlockコマンドをPOSTするだけです。

ショートカットアプリを開き ショートカットを作成 しましょう。

ショートカット自体については解説しませんので、次のような記事を参考にしてみてください。

tech-blog.rakus.co.jp

🔗 URL

まず URLAPIURI を設定します。 00000000-0000-0000-0000-000000000001 の部分は、確認したデバイスID device_id に置き換えてください。

https://api.candyhouse.co/public/sesame/00000000-0000-0000-0000-000000000001

⬇️ URLの内容を取得

つぎに URLの内容を取得POST する内容を設定します。

詳細より「方法」は POST を選択します。

「ヘッダ」には Authorization キーに API Key を値(テキスト)として1組だけ入れます。

「本文を要求」には「JSON」形式で command キーに lock を値(テキスト)として1組だけ入れます。

適宜、アイコンを🔒マークなどにし、ホーム画面に追加すれば利用できます。

unlock も同様に(別々に)作成しておくと便利です。

うまく動かないときは

APIURIが間違ってないか、デバイスIDやAPI Keyが間違ってないかなどを確認してみてください。 ターミナルから curl コマンドで実行できているということであれば、ショートカットの設定に問題がある可能性が高いです。

Google Apps Script で API を使った操作をしたい場合は

次のWebhookを使う際に使用するライブラリを使うと、とても簡単に扱うことが可能です。

SESAMEの状態変更時のWebhookを利用しGoogleスプレッドシートにログを自動記録する

Webhookとは、何かしらのイベントをトリガー(きっかけ)にして、(今回であればSESAME側から)GETやPOSTでデータが飛んでくることを言います。 Webコールバックとか、HTTPプッシュAPIとかとも言われるようです。

SESAMEの場合は、アプリや物理鍵を使って施錠・解錠が行われたタイミングで ダッシュボードで指定するWebhookのURLに対し POST(もしくはGET)で飛んできます。

次のようなデータが得られます。

  {
    "device_id": "00000000-0000-0000-0000-000000000000",
    "locked": true
  }

マニュアルには state として locked / unlocked が返ってくると記載されていますが、実際は上記のような内容で返ってきています。
今回使用するライブラリを使用することで state のほか、 unlocked というキーを足し、次のような形式で取得できます。

  {
    "device_id": "00000000-0000-0000-0000-000000000000",
    "locked": true,
    "state": "locked",
    "unlocked": false
  }

今回使用する Google Apps Script の ライブラリ

今回使用する SESAME-Google-Apps-Script-Library はこちらです。

github.com

わたし自身が Google Apps Script の ライブラリの使用が初めてですので、(自分用のメモを兼ねて)基本的な利用方法から解説します。

新規の Google Apps Script を立ち上げる

新規の Google Apps Script の作成は、次の2通りがあります。

  1. Googleドライブの[+新規]ボタンよりその他 ‣Google Apps Scriptの順で選択する
  2. Googleスプレッドシートのメニューのツールスクリプトエディタの順で選択する

今回はログ記録のためにスプレッドシートを使用しますので、後者でよいでしょう。 もしとくにスプレッドシートを使用しない場合や、複数のスプレッドシートを使用するなどの場合は、前者にしてもよいでしょう。

ライブラリを読み込む

メニューよりリソースライブラリ… を選択します。

Add a Library に APP ID MhGyvaXUzLZgSUv835brogVVeyfhHcqFG を入力し追加します。

利用するバージョン を最新版(1番大きな数字)にします。

Identifier の欄に任意の名称を入力します。 とくに問題がなければ、下記の例と同様「Sesame」のまま使用してください。

API Key を[スクリプトのプロパティ]に保存する

API Key について、JavaScript ファイルの先頭で次のように記述することもできますが

var API_KEY = 'Su_2sdekmPfE...IvBgtPYSvv4wz_qrByQr7le_hh';

大切な情報ですので、なるべくコード内に埋め込まない運用をしたいところです。

メニューの ファイルプロジェクトのプロパティ にある スクリプトのプロパティ に保存しておくと次のように取得可能です。

// API_KEYというキーで保存した場合の例
var apiKey = PropertiesService.getScriptProperties().getProperty("API_KEY");

ライブラリを試めしてみる

実際に利用できるか確認しましょう

function myFunction() {
  var apiKey = PropertiesService.getScriptProperties().getProperty("API_KEY");
  // 次のようにインスタンスを作成することができます
  var client = Sesame.create({apiKey: apiKey});
  var results = client.getDeviceList();
  console.log(results);
}

メニューの[リソース]の下くらいにある関数を選択 ▾からmyFunctionを選択し、ふたつ左にある▶︎をクリックし実行します。 ⌘+Enterもしくはメニューの表示ログで、デバイスIDdevice_idの確認が可能です。

Webhook 利用時に呼ばれる doPost() / doGet() を記述する

doPost()doGet()は、ウェブアプリケーションとして公開した際に呼ばれる特別な関数です。 SESAMEのWebhookはどちらで呼ぶことも可能です。

どちらか片方だけ記述すればOKですが、あとで困らないよう次のようにしておくこともできます。

function doGet(e) {
  log2sheet(e);
  return ContentService.createTextOutput("OK").setMimeType(ContentService.MimeType.TEXT);
}

function doPost(e) {
  return doGet(e);
}

function log2sheet(e) {
  // 後述
}

ログ用のシートを作成する

スプレッドシートのシート名をlogのように(任意で)変更しておきます。

1行目をタイトル行として、たとえばA1timestampB1stateC1deviceのようにしておきます。

メインのロジックを記述する

スプレッドシートのURLよりスプレッドシートIDをコピーし、コード内のSpreadSheet_ID _HEREの箇所を置き換えてください。

function log2sheet(e) {
  // parseWebhookContentsはインスタンス不要
  var contents = Sesame.parseWebhookContents(e);
  var sheet = SpreadsheetApp.openById('SpreadSheet_ID _HERE').getSheetByName('log');
  var lastRow = 1 + sheet.getDataRange().getLastRow();
  var timestamp = new Date();
  var data = [
    timestamp,
    contents.state,
    contents.device_id
  ]
  sheet.getRange(lastRow, 1, 1, data.length).setValues([data]);
}

期待した動作をしてくれるか確認するコードを書いてみましょう。

function testWebhook() {
  var e = {"contextPath":"","parameter":{},"queryString":"","postData":{"contents":"{\"device_id\": \"dummy-id\", \"locked\": true}","length":69,"name":"postData","type":"application/json"},"parameters":{},"contentLength":69};
  var contents = Sesame.parseWebhookContents(e);
  log2sheet(e);
  console.log(contents.state); // locked
}

上述の方法と同様に実行してみてください。
「log」シートに locked と書かれたデータが入っていれば成功です。

実行の許可を求められたら許可をしてください。
「このアプリは確認されていません」と出たら、[詳細]というリンクを開く必要があります。

ウェブアプリケーションとして公開する

Webhookのデータを受け取るため、Google Apps Script を外部に公開しましょう。

メニューの公開ウェブアプリケーションとして導入 …を選択します。

プロジェクトのバージョン新規作成にし、適宜コメントを入れます。

次のユーザーとしてアプリケーションを実行自分にします。

アプリケーションにアクセスできるユーザー を、外部(SESAME)からアクセスできるよう全員(匿名ユーザを含む)にします。

導入をクリックすると、現在のウェブアプリケーションのURLが表示されるのでクリップボードにコピーしましょう。

注意事項

公開するとURLにGETやPOSTをすることで doGet() や doPost() が外部から呼び出せるようになるのですが、コードを編集した場合は次の点に注意が必要です。

  • 再度公開ウェブアプリケーションとして導入 …を行い、バージョンを新規作成する
  • ウェブアプリケーションのURLが変わる場合がある

バージョンをあげないと、いつまで経ってもWebhookは古いコードのほうを実行してしまいます。

SESAMEダッシュボードにWebhook用のURLを登録

CANDY HOUSE Dashboard にアクセスします。

左側のメニューの[API設定]を開き「コードを送信する」をクリックし送られてくるメールの検証コードを入力するとページが表示されます。

Webhookの[Edit]ボタンをクリックし、URLをペーストし追加します。 (GETとPOSTはどちらでも構いません)

動作確認

上述のショートカットを起動してみて、実行後スプレッドシートに記入されるかを確認してみてください。

Webhookが飛んでこない場合

じつはわたしも、自分のアプリで開閉したときや、物理鍵で開閉したときなど、一部のケースでWebhookが飛んでこなくて困っています。

情報求む。

Google Apps Script で簡単にSESAMEAPIを扱うためのライブラリを公開

今回の開発時にはじめてGoogle Apps Script のライブラリというものを知ったので、SESAME APIsにアクセスするためのライブラリを作ろうと思い立ちました。

ライブラリにしておくメリットとしては、APIの仕様変更時にライブラリの修正のみで対応が可能になることや、複数のアプリケーションで使い回す際に便利といったところでしょうか。

また、このブログ記事を書いていることもそうですが、1年以上経ってコードを見直す際にすっかり記憶が抜け落ちていても対応がしやすくなります。 経験的にこのあたりは、期待した動作をしてくれた後ほっとしている時間が長くなればなるほど書くのが面倒になってくるので、記憶が鮮明なうちに勢いで書いてしまうほうが良いですね。

ライブラリの設計

今回達成したかったのはおもに次のような点です。

  • メソッド名をみれば何ができるか想像がつくようにしたい
  • 引数をみれば何を渡せばよいか想像がつくようにしたい
  • 実行することが明白な手順が複数あれば可能な限り一度に実行できるようにしたい
  • Webhook利用時にどんな形式のデータが飛んでくるか分かっていなくても扱えるようにしたい
  • API Reference を読まずに開発に入れるようにしたい

ライブラリの開発時に参考にした情報

officeforest.org

Google Apps Script のライブラリについてひととおり理解できます。

qiita.com

コード自体が参考になりました。

qiita.com

同じ方の記事。 いろいろTipsが載っています。

www.pnkts.net

GCPアカウントが必要なったという情報があったので、そのあたりも画像になっていて理解しやすかったです。

google-apps-script.net

同じくGCPアカウントが必要なったという情報があったので、そのあたりも画像になっていて理解しやすかったです。

記事のとおりに記述するだけでお手軽にライブラリ化ができますので、再利用しやすくするためにもぜひ活用していきたいですね。

さいごに

扱いやすいAPIがあってとても便利に活用できそうです。

今後はGoogleスプレッドシートGoogleカレンダーの情報をもとに、時間になったらセミナールームの解錠が行われるような機能を作っていきたいと思っています。 いろんな可能性が広がって嬉しい🙂

みなさんもぜひ活用していきましょうね。