知識のアウトプットをするブログ

なんでもブログに書き記す

【Google Assistant】家電をIRKitで音声操作する

f:id:seisyo58:20181103163931j:plain
我が家の家電制御の方法が変化したので、ここに書き記す。
なお、IRKit × IFTTT × GASの組み合わせで実現している。

大まかな流れ

f:id:seisyo58:20181103104304j:plain

  1. Google Homeに「リモコン 電気つけて」と話しかける
  2. IFTTTでメッセージを読み取り、GASへ「電気つけて」と送られる
  3. GASで「電気つけて」に対応した赤外線信号をIRKitへ送信
  4. IRKitが赤外線で照明をつける

という流れだ。

余談 これまでどうしていたか

今までラズベリーパイでJuliusを用いた音声認識curlでのローカル内での信号送信を行っていた。
方法を変えようと思ったのは、Juliusの音声認識よりも、Google Homeでの音声認識の方が精度が高かったから。

GAS

GASとは、Google Apps Scriptのこと。Google Drive上に置いたGASファイルをサーバーとかを用意しなくても実行することが出来る。GASの中身はJavaScriptで記述が出来る。ただしJSの中でも、使えない関数などがあったりするので、そこは注意が必要だ。

GASファイルを用意する

Google Driveの[新規]
f:id:seisyo58:20181103110750j:plain

[その他]の[Google Apps Script]
f:id:seisyo58:20181103110829j:plain

[無題のプロジェクト]をわかりやすいプロジェクト名に変更する
f:id:seisyo58:20181103110923j:plain
f:id:seisyo58:20181103111011j:plain

GASを記述する

最初に全貌

function doPost(e) {
  var str = e.postData.getDataAsString();//str:電気つけて
  str = str.replace(/\s+/g, "");//不要な空白を削除
  readSpreadsheets(str);
}

//スプレッドシートから検索して、送信するデータを決定する
function readSpreadsheets(str){
  var spreadsheet = SpreadsheetApp.openById('<スプレッドシートのID>');
  var sheet=spreadsheet.getSheetByName('irkit');
  var values = sheet.getRange(1,1,sheet.getLastRow(),sheet.getLastColumn()).getValues();
  values.forEach(function(elem){
    if(elem.indexOf(str)!=-1){
      sendMessage(elem[0]);
    }
  });
}

//データを送信する
function sendMessage(message){
  var postUrl='https://api.getirkit.com/1/messages';
  var jsonData=
      {
        "clientkey":"<クライアントキー>",
        "deviceid":"<デバイスID>",
        'message':message
      };
  var payload=JSON.stringify(jsonData);
  
  var options=
      {
        "method":"post",
        "contentType":"application/json",
        "payload":payload
      };
  UrlFetchApp.fetch(postUrl,options);
}

関数を1つづつ見ていこう

function doPost(e) {
  var str = e.postData.getDataAsString();//str:リモコン 電気つけて
  str = str.replace(/\s+/g, "");//不要な空白を削除
  readSpreadsheets(str);
}

doPost(e)は、IFTTTからデータを受信するための関数だ。

function readSpreadsheets(str){
  var spreadsheet = SpreadsheetApp.openById('<スプレッドシートのID>');
  var sheet=spreadsheet.getSheetByName('irkit');
  var values = sheet.getRange(1,1,sheet.getLastRow(),sheet.getLastColumn()).getValues();
  values.forEach(function(elem){
    if(elem.indexOf(str)!=-1){
      sendMessage(elem[0]);
    }
  });
}

この関数では、スプレッドシートスプレッドシートのIDで開き、その中の"irkit"というシートの情報を2次元配列で取得している。
ちなみにこのスプレッドシートの情報は以下のようになっている。
f:id:seisyo58:20181103115336j:plain

function sendMessage(message){
  var postUrl='https://api.getirkit.com/1/messages';
  var jsonData=
      {
        "clientkey":"<クライアントキー>",
        "deviceid":"<デバイスID>",
        'message':message
      };
  var payload=JSON.stringify(jsonData);
  
  var options=
      {
        "method":"post",
        "contentType":"application/json",
        "payload":payload
      };
  UrlFetchApp.fetch(postUrl,options);
}

最後に、IRKitに信号を送るためのプログラムだ。POSTデータを送信する。

外部からGASを実行できるようにする

[公開]の[ウェブ アプリケーションとして導入]
f:id:seisyo58:20181103114326j:plain
アクセスできるユーザーを匿名ユーザーも含むように変更し、[導入]
f:id:seisyo58:20181103114403j:plain
ここにアクセスするためのURLが記されているので、控えておく。
f:id:seisyo58:20181103114449j:plain

IFTTT

IFTTTについての説明は省略する。簡単にいうと「アレをしたらコレをする」というサービス。

thisを設定

f:id:seisyo58:20181103114557j:plain
Google Assistantを選択
f:id:seisyo58:20181103114611j:plain
左から3つ目を選択
f:id:seisyo58:20181103114712j:plain
以下のように設定
f:id:seisyo58:20181103114728j:plain

thatを設定

f:id:seisyo58:20181103114737j:plain
Webhooksを選択
f:id:seisyo58:20181103114749j:plain
選択肢がひとつなので、それを選択
f:id:seisyo58:20181103114812j:plain
URLに先程控えたURLを設定
f:id:seisyo58:20181103114926j:plain

これで設定完了だ。
f:id:seisyo58:20181103115003j:plain

まとめ

IFTTT×GASによる可能性は無限大だ。IFTTTだけでも様々なことができるが、GASを組み合わせると、さらにいろんなことができるようになる。興味を持った人は、ぜひチャレンジしてみてほしい。


IFTTTの過去記事
seisyo58.hatenablog.com