【SESAME mini】 GASとの連携方法

活用アイデアに続いて、具体的なコードの書き方。(活用アイデアはこちら
とりあえず、複数台同時操作とトグルに対応するサンプルを作ってみる。

【まず、GASの新規作成】

  1. Googleドライブを開いて、新規→その他→Google Apps Script
  2. 適当に名前をつける。

【スクリプトプロパティを保存】

  1. ファイル→プロジェクトのプロパティ→スクリプトのプロパティ
  2. 事前に取得したAPIキーやデバイスIDをプロパティに記入→保存



    APIKey:セサミAPIキー
    myKey:認証キー ※
    玄関:セサミのデバイスID
    玄関カウント:0
    以下、複数台ある場合の例
    玄関2:セサミのデバイスID
    玄関2カウント:0
    倉庫:セサミのデバイスID
    倉庫カウント:0


※認証キーは第三者のアクセスをはじく簡易セキュリティ対策。任意の長い文字列を記入する。(エスケープが必要な記号は使用しないほうが運用しやすい) 
プロパティ名(左側)は、太字の部分以外は任意の名前でOK。
例:「玄関」「玄関カウント」は、「SESAME1」「SESAME1カウント」などに変更可。


【コードを記入(サンプル)】


var property = PropertiesService.getScriptProperties();
var myKey = property.getProperty('myKey');
var head = {'Authorization': property.getProperty('APIKey')};
var endpoint = 'https://api.candyhouse.co/public/sesame/';

function debug() {
  main(myKey,"玄関","2");
}

function doPost(e) {
  var p = JSON.parse(e.postData.contents);
  main(p.myKey,p.deviceName,p.command);
}

function doGet(e) {
  var p = e.parameter;
  main(p.myKey,p.deviceName,p.command);
}

//ロック状態取得 true/false
function isLocked(deviceName) {
  var deviceID = property.getProperty(deviceName);
  var url = endpoint + deviceID;
  var options = {
    headers: head,
    method: 'GET'
  };
  var res = UrlFetchApp.fetch(url, options).getContentText();
  return JSON.parse(res).locked;
}

function main(key,deviceName,command) { //command:0=解錠,1=施錠,2=状態チェック型のトグル,3=回数型のトグル
  if(key != myKey)
    return;

  var devices = deviceName.split(',');
  var c = parseInt(command);
  if(c == 2)
    c = 1 - isLocked(devices[0]);//trueは1、falseは0とみなされる
  if(c == 3) {
    var target = devices[0] + 'カウント';
    var count = parseInt(property.getProperty(target)) + 1;
    c = count % 2;
    property.setProperty(target, count);
  }

  var control = ['unlock','lock'][c];
  devices.forEach(function(name) {
    var deviceID = property.getProperty(name);
    var url = endpoint + deviceID;
    var options = {
      headers: head,
      method: 'POST',
      contentType: 'application/json',
      payload: JSON.stringify({'command':control})
    };
    UrlFetchApp.fetch(url, options);
  });
}

【補足説明】
状態チェック型のトグルとは
サーバーに現在のセサミの状態を問い合わせ、その逆の動作をさせる。ロック中ならアンロック、アンロック中ならロックという形。

回数型のトグルとは
起動ごとに(つまり、Dashボタンなら押すたびに)動作が入れ替わる。(奇数回目ならロック、偶数回目ならアンロック)

回数型を設置した理由
手動の操作がサーバーに反映されるのが即時ではないため、例えば出かける際、手動で開けて外に出てすぐにDashボタンを押しても、まだロック中と認識され解錠処理をしてしまう可能性がある。こうした利用が見込まれる場合、回数型の方が適している場合がある。

myKeyについて
APIキーを逐一送信させる方法もあるけど、個人的には格納しておきたい(送信するデータに含めたくない)ので、代わりに独自の認証キーを使用している。


【動作チェック】
「関数を選択」をdebugにして、実行ボタンを押す。
注:プロパティ名を「玄関」以外にした場合は、その前にdebugファンクションを書き換え。

成功したら、SESAMEが動く。



成功したら、

【ウェブアプリケーションにする】

  1. 公開→ウェブアプリケーションとして導入
  2. プロジェクトバージョンがNew(新規作成)になっていることを確認
  3. アクセスできるユーザーを「全員(匿名ユーザーを含む)」に。
  4. 更新を押して、「承認が必要です」と出たら、「許可を確認」→ログイン→「許可」
  5. 最後にURLをコピーしておく。


【運用】

あとは、このURLに適切にHTTPリクエストを送れば起動される。
使用例としては、

  • Dashボタン用のラズパイから
  • IFTTTのアクション(Webhooks)から
  • MacroDroidのアクション(Webサイトを開く→HTTP GET)から
など。

POSTの Content-Type は、application/json
基本的にはPOSTメソッドが良いと思うけど、MacroDroidからはGETメソッドしか送れないため、doGetとdoPost両方用意している。

必要なパラメータは、myKeydeviceNamecommandの3つ。

  • myKeyがスクリプトプロパティの値と一致しないと、はじかれる。
  • deviceNameは、スクリプトプロパティにプロパティ名として登録した名前。
    サンプルでは「玄関」。複数台同時に動かしたい場合は、カンマ区切りで「玄関,玄関2,倉庫」のように。
    ※複数台のトグルコマンドのときは先頭のデバイスが判断基準。
  • commandは数字で、0~3
    0=解錠,1=施錠,2=状態チェック型のトグル,3=回数型のトグル

なお、エラー処理は省いているため、成功しても失敗しても特にわからない。セサミが実際に動けば成功。

※APIはGAS利用にかかわらず、外部からのアクセスを “完全に” 遮断するセキュリティはないので、あくまで自己責任で。(キーがバレなければ基本的には大丈夫)

【スクリプト更新時の注意点】

スクリプトを編集した場合、保存ボタンを押しただけではウェブアプリケーションには反映されない。反映させるには、再度「公開→ウェブアプリケーションとして導入」が必要。その際、プロジェクトバージョンをNew(新規作成)にするのを忘れず。

7 件のコメント:

  1. https://api.candyhouse.co/public/sesame/sesame のリクエストに失敗しました(エラー: 400)。サーバー応答の一部: {"error": "BAD_PARAMS"}(応答の全文を見るには muteHttpExceptions オプションを使用してください)(行 28、ファイル「コード」)

    上記のようなエラーが発生します。
    セサミIDを足してもダメでした。
    解決方法はありますでしょうか。

    返信削除
    返信
    1. こんにちは。
      この情報だけで明確な原因はわかりかねるのですが、アプリ側でクラウド連携の許可はされていますか?
      「セサミの管理」から「クラウド」をONにします。

      削除
  2. こんにちは。
    sesame miniを使用しています。
    コードをPC上で実行すると
    解錠←→施錠はうまくいくのですが、
    ウェブアプリにしてMACRODROIDにて実行しようとしてもうまくいきません。
    《下記のような設定をしています》
     【アクション】
       [Webサイトを開く/HTTP GET]で
       https://script.google.com/~/exec
       □エンコード・パラメータURL
       ■HTTP GET (Webブラウザ不使用)
       □完了するまで次のアクションをブロック
       □「成功」を真偽変数に代入する
       □HTTPレスポンスを文字列変数に代入
     【ローカル変数】
      (整)command 値:2
      (文)deviceName 値:玄関
      (文)myKey 値:任意のパスワード

    御手隙の時間にでも教えていただけないでしょうか?

    返信削除
  3. こんにちは
    MacrodroidでのHTTP GETでの指定方法を教えていただけないでしょうか。
    《Webサイトを開く/HTTP GET》の設定で
    [エンコード・パラメータURL]をチェックして、
    https://script.google.com/~/exec?myKey=●&deviceName=▲&command=■
    であれば上手くいくのですが、
    [HTTP GET(Webブラウザ不使用)]のチェックだと反応がありません。

    返信削除
    返信
    1. こんにちは、返信が遅くなりすいません。
      「エンコード・パラメータURL」と「HTTP GET (Webブラウザ不使用)」、両方にチェックを入れた場合どうでしょうか?私はそのようにして問題なく動作しています。

      ちなみにURLも変数に入れていて、以下のようにしています。関係ないと思いますが、もしうまくいかないようでしたらこちらの方法も試してみてください。

      URL欄:[v=URL][v=Key][v=URL2]2

      変数
      URL 値:https://script.google.com/~/exec?myKey=
      Key 値:********
      URL2 値:&deviceName=SESAME&command=

      削除
  4. 回答ありがとうございます。
    変数を使用する方法を試してみました。
    やはり…
     ■エンコード・パラメータURL
     □HTTP GET(Webブラウザ不使用)
    では上手くいきますが、
     ■エンコード・パラメータURL
     ■HTTP GET(Webブラウザ不使用)
    では反応しません。
     □エンコード・パラメータURL
     ■HTTP GET(Webブラウザ不使用)
    でも反応しませんでした。
    エンコード・パラメータURLを使用する方法は、
    かなり反応が良いので残念です。
    おそらく、自分の環境に何か原因があるのだと思います。

    現在、TaskerとHTTP ShortcutでWeb APIにアクセスする方法で
    運用しています。この方法は割と安定しているので、しばらく
    この方法で運用したいと思います。
    ありがとうございました。

    返信削除
    返信
    1. んー、そうなんですね。こちらではうまくいくのでちょっとわかりませんね。

      そうですね、好きな経路で自由に利用できるのがAPIのいいところですし、それぞれの環境で最適な方法を使ってもらえればと思います。

      削除