見出し画像

BOCCO emo外部連携(IFTTT)の代替方法

〜注意〜
本記事は以下のモデルのBOCCO emoのみに対応しています。

BOCCO emo Wi-Fiモデル(型番:YE-RB010-GWNJP, TG-RB010-GWNJP, NP-RB010-GWNJP)
BOCCO emo LTEレンタルモデル(型番:YE-RB010-GSNJP)

※型番はBOCCO emo本体の底面をご確認ください。

はじめに

こんにちは。
ユカイ工学コネクティブエンジニアの宮﨑です。
私は主に、BOCCO emoのソフトウェアの開発を担当しています。

IFTTT(イフト)連携サービスの廃止についてのお知らせの通り、2024年4月25日より、BOCCO及びBOCCO emoでIFTTT(イフト)連携サービスが廃止となります。
しかし、事前アンケートでは、ユーザー様から、代替方法の検討を望む声を多くいただいておりました。そこで、今回はIFTTT連携の機能を代替する方法をご案内します。

本記事ではIFTTTからBOCCO emo platform APIを活用して、BOCCO emoに発話させる方法をご紹介します。一部、プログラミングコードを入力していただきますが、コピー&ペーストで対応できます。

所要時間:30分~60分
必要なもの:パソコン

用語解説

  • IFTTT(イフト)

    • 様々なシステムと連携させることができるサービス。

  • Google Sheets

    • Google社が提供する、表計算プログラム。

  • Google Apps Script

    • Google社が提供する、プログラミング環境。同社が提供するGoogle Sheetsなどと連携可能。

  • BOCCO emo Platform API


全体説明

本記事で構築するシステムの全体像です。

システム全体像

【手順1】 BOCCO emo platform APIを利用するための認証情報の取得

BOCCO emo platform APIのログイン画面を開きます。

開発者の方>「BOCCOアカウントでログイン」をクリックします。

BOCCOアカウントのメールアドレス及びパスワード(普段お使いのBOCCO emoアプリでログインしているもの)を入力し、利用規約同意のチェックボックスをチェックした後に、「ログイン」をクリックします。

権限付与の確認が表示されます。
「許可する」をクリックします。

ダッシュボードが表示されます。
ダッシュボードの「リフレッシュトークン」を、【手順2】で使用するのでコピーして控えておきます。


【手順2】 Google Sheetsの構築

Google Sheetsを利用して、BOCCO emoと連携します。

Googleアカウントをお持ちで無い方は事前にGoogleアカウントの作成をお願いします。

Google Driveのサイトを開きます。

「ドライブを開く」をクリックします。

画面左上の「+新規」ボタンをクリックし、「IFTTT」というフォルダを作ります。

作成した「IFTTT」フォルダに移動し、画面左上の、「+新規」>「Google スプレッドシート」>「空白のスプレッドシート」をクリックし、新しいスプレッドシートを作成します。

新しいスプレッドシートを作成することができました。

分かりやすいように、「BOCCO emo発話シート」に名前を変更しておきます。
画面左上の「無題のスプレッドシート」をクリックすると、変更できます。

これからGoogle Apps Scriptを編集していきます。
画面上のメニューの「拡張機能」>「Apps Script」をクリックします。

スプレッドシートに対応した、スクリプトが新規作成されました。

分かりやすいように、「BOCCO emo発話スクリプト」と名前を変更します。
画面上の「無題のプロジェクト」をクリックすると、名前が変更できます。

画面右の入力欄を一度空にした後に、下記のスクリプトをコピー&ペーストします。

const baseUrl = 'https://platform-api.bocco.me'
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();


function setRooms(index = 0) {
 try {
   const requestUrl = baseUrl + '/v1/rooms';
   const response = UrlFetchApp.fetch(requestUrl, {
     'method': 'get',
     'headers': {
       'Content-Type': 'application/json',
       'Authorization': 'Bearer ' + getAccessToken()
     }
   });
   const rooms = JSON.parse(response.getContentText()).rooms
   if(rooms.length === 0){
     throw new Error('対応モデルの部屋が存在していません。')
   }
   rooms.forEach(function (room) {
     Logger.log('部屋名: ' + room.name + ', uuid: ' + room.uuid)
   });
   PropertiesService.getScriptProperties().setProperty('ROOM_UUID', rooms[index].uuid);
   Logger.log("部屋を「" + rooms[index].name + "」に設定しました。")
   return true
 } catch (e) {
   Logger.log(e.message);
   return null;
 }
}


function sendMessage(text = "テストメッセージ") {
 try {
   const roomUuid = PropertiesService.getScriptProperties().getProperty("ROOM_UUID")
   var requestUrl = baseUrl + '/v1/rooms/' + roomUuid + '/messages/text';
   var response = UrlFetchApp.fetch(requestUrl, {
     'method': 'post',
     'payload': JSON.stringify({ "immediate": true, 'text': text }),
     'headers': {
       'Content-Type': 'application/json',
       'Authorization': 'Bearer ' + getAccessToken()
     }
   });
   return response.getResponseCode === 200;
 }
 catch (e) {
   Logger.log(e.message);
   return false;
 }
}


function refresh() {
 Logger.log("refresh token")
 const refleshToken = PropertiesService.getScriptProperties().getProperty("REFRESH_TOKEN")
 try {
   var requestUrl = baseUrl + '/oauth/token/refresh';
   var response = UrlFetchApp.fetch(requestUrl, {
     'method': 'post',
     'payload': JSON.stringify({ 'refresh_token': refleshToken }),
     'headers': { 'Content-Type': 'application/json' }
   });
   return JSON.parse(response.getContentText()).access_token;
 } catch (e) {
   Logger.log(e.message);
   return null;
 }
}


function getAccessToken() {
 const currentTime = new Date();
 const accessToken = PropertiesService.getScriptProperties().getProperty("ACCESS_TOKEN")
 const expireTime = PropertiesService.getScriptProperties().getProperty("EXPIRE_TIME")
 if (accessToken === null || (new Date(expireTime).getTime() < currentTime.getTime())) {
   //プロパティに無い、もしくは期限切れの場合はリフレッシュする。
   const newAccessToken = refresh()
   // 50分後の時刻を計算
   const newExpireTime = new Date(currentTime.getTime() + (50 * 60 * 1000)); // 50分 = 50 * 60秒 * 1000ミリ秒
   PropertiesService.getScriptProperties().setProperty("ACCESS_TOKEN", newAccessToken)
   PropertiesService.getScriptProperties().setProperty("EXPIRE_TIME", newExpireTime)
   return newAccessToken
 } else {
   //期限がまだ残っていればそのまま返す。
   return accessToken
 }
}


function getAColumnValues() {
 var columnAValues = sheet.getRange("A:A").getValues();
 var aColumnList = [];
 for (var i = 0; i < columnAValues.length; i++) {
   if (columnAValues[i][0] !== "") {
     aColumnList.push(columnAValues[i][0]);
   }
 }
 return aColumnList;
}


function setAColumnValues() {
 restMessages.forEach(function (restMessage, index) {
   sheet.getRange(index + 1, 1).setValue(restMessage);
 });
}


function trigger() {
 const columnAValues = getAColumnValues()
 const messages = columnAValues.slice(0, 5);
 const restMessages = columnAValues.slice(5);
 //発話データがあれば発話、なければ終了
 if (messages.length > 0) {
   messages.forEach(function (message) {
     sendMessage(message)
   });
 } else {
   return
 }
 // 一旦全てのデータを削除
 sheet.getRange("A:A").clear();
 // 未発話のデータがあったら、戻す。
 if (restMessages.length > 0) {
   setAColumnValues(restMessages)
 }
}

入力完了すると、上記のような画面になります。

次に、【手順1】のダッシュボードで控えたリフレッシュトークンをスクリプトに設定します。

画面左側の「プロジェクトの設定」をクリックします。

一番下までスクロールし、「スクリプト プロパティを追加」をクリックします。

「プロパティ」に"REFRESH_TOKEN"という文字を、値に【手順1】で取得したリフレッシュトークンを入力します。
「スクリプト プロパティを保存」をクリックし、設定を反映します。

左のメニューから「エディタ」をクリックし、元の画面に戻ります。

ここで一旦、設定が反映されているか、確認します。
画面上の「保存」をクリックした後に「実行」をクリックします。

承認を求められる画面が表示されます。
案内に従い、許可します。

成功すると、登録している部屋分の情報が表示され、最後に「部屋を「(ユーザー様が設定した部屋の名前)」に設定しました。」と表示されます。

ここでBOCCO emoを複数登録している方は追加で設定が必要です。

上記4行目のindexの数字は指定する部屋の番号を指します。
初期値は0になっているので、一番最初に表示される部屋が設定されます。
もし、一番最初以外の部屋に、メッセージを投稿したい場合は、こちらの数字を変更してください。
変更後、再度「実行」し、指定した部屋が設定されることを確認してください。

次に、設定したスクリプトを定期的に実行する設定を行います。

画面左の「トリガー」をクリックします。

画面右下の「+トリガーを追加」をクリックし、トリガーの設定を行います。
10分置き※ にtriggerという関数を実行するように設定します。
上記スクリーンショットと同様の設定を行ってください

  • 実行する関数

    • trigger

  • 実行するデプロイを選択

    • Head

  • イベントのソースを選択

    • 時間主導型

  • 時間ベースのトリガーのタイプを選択

    • 分ベースのタイマー

  • 時間の間隔を選択(分)

    • 10分

 Google Apps Scriptの無料枠の制限である、「トリガーの合計実行時間:90 分 / 日」を鑑み、10分に1回、実行するように設定しています。

設定が完了したら、「保存」をクリックし、設定を反映してください。

上記のように、設定したトリガーが表示されたら、設定完了です。

これで、Google Sheetsの構築は完了です。


【手順3】 IFTTT連携

最後に、IFTTTと連携していきます。
IFTTTのアカウントをまだお持ちでない方は作成してください。

IFTTTにログインします。

ログインが完了したら、画面上の「Create」をクリックします。

IFTTTのアプレット(自動化する設定)を作成していきます。
今回は例として、日没の時間が近づいたらBOCCO emoがお知らせするアプレットを作成します。

If Thisをクリックします。

検索欄に「weather」と入力し、表示された「Weather Underground」をクリックします。

「日没」を意味する、「Sunset」をクリックします。

場所を設定します。
地図で、設定したい場所をクリックします。
完了したら、Create triggerをクリックします。

次に、「Then That」をクリックします。

検索欄に「google」と入力し、表示された「Google Sheets」をクリックします。

今回は発話させたい内容をスプレッドシートに追加してもらうため、「Add row to spreadsheet」をクリックします。

上記のように設定します。
「Spreadsheet name」は【手順1】で設定した名前にしてください。
Drive folder pathは空欄にしてください。

Continueをクリックします。

Applet Titleを、分かりやすいように「日の入りが近づいたらスプレッドシートに追記」に変更します。
Finishを押して、作成します。

これで全ての設定が完了しました。


動かないときは?

以下のどちらに問題があるか、確認します。

  • IFTTT

  • Google Sheets

IFTTTのアプレットの画面を開いてください。

アプレットの実行履歴である、「View Activity」をクリックします。

スクリーンショットは成功時の例です。
失敗している場合は赤文字で問題のある箇所が表示されます。
失敗箇所の原因を読んで対応してください。
スクリーンショットと同様に成功している場合は、IFTTTの設定は問題ありません。
【手順2】に戻り、Google Sheetsの設定を再度ご確認ください。


すぐに発話させたいときは?

上記の設定を応用し、Google Sheetsからユーザー様がクリックしたタイミングで発話できるようにします。

発話設定を行ったシートを開きます。

画面上の、「拡張機能」>「マクロ」>「マクロをインポート」をクリックします。

一番下に表示される、「trigger」という箇所の「関数を追加」をクリックします。

BOCCO emoに発話させたい内容を、A列に入力します。
画面上の、「拡張機能」>「マクロ」>「trigger」をクリックします。

これにより、10分間隔ではなく、すぐにメッセージを送信することができます。
パソコンからBOCCO emoに発話させたいときなどに、ご活用ください。


おわりに

無事に設定できましたでしょうか?
これを機に、BOCCO emo Platform APIを楽しんでいただければ何よりです。
これからも生活がより楽しくなるような連携記事を書いていきますので、よろしくお願いします。


BOCCO emo APIsの活用事例をご覧いただけます



この記事が気に入ったらサポートをしてみませんか?