Google Home と Akerunで簡単スマートオフィス

CTOの@kazuphです(この記事は前年のアドベントカレンダーの居残りエントリーです(汗))。

Google Home、みなさん買いましたか?

僕という意味では会社で2台、家用に1台購入して遊んでいます。 HomeごとにGoogleのアカウントを分けて管理できるので、プライバシーも守られていていい感じです。

うちの会社では元々数台のChromeCastを使って遊んだり業務用に使っていましたが、 ここにGoogle Homeを加えたときにどうなるかやってみました。

やりたいこと

  • 手っ取り早くAkerunと連携したい
  • 受付に人が来たら音声で教えてほしい

ということでやってみましょう。

Akerun連携する

Akerunで開閉があったらGoogle Homeが教えてくれるようにしてみましょう。

今回は全部ができる一つのプログラムを書くのではなく、 一つのことをする複数のプログラムを掛け合わせてて作成します。

Akerunで投稿があったらSlackに通知する

方法はいくつかあります。

  • YahooさんのmyThingsを使う(プログラミングなし)
  • 公開版のAkerun 履歴 APIを使う
  • (中の人のみ)社内向けのAkerun APIを使う

myThingsさんの方法が簡単です。 ですが、こちらである程度制御したかったので、今回は社内向けのAPIでやってしまいましたのでソースは割愛(え)。

Slackの通知を見てGoogle Homeにテキスト送信

ここでは特定のSlackチャンネルの投稿があったらGoogle HomeAPIを叩くことを考えます。言わば中継役です。

今回はGASで実装してみました。

doPostで

  • Slackからのoutgoingのwebhookのmessageを受け取り
  • ローカルネットワーク内で立ち上がってるサーバーのngrok上でのURLの受け取り

をやっています。

テキストで受け取った場合は、それをそのまま後述するngrokで公開されているURLにポストします。ngrokのURLは起動時に毎回変わるので、今回はそのURLを中継役のGASにpostすることで、プログラムを書き換えなくても自動で連携するようにしています。

function doPost(e) {
  if ("AAAAAA..." === e.parameter.token) { 
    var text = e.parameter.text;
    text = text;
    return request(text);
  }
  if ("BBBBBB..." === e.parameter.token) {
    var url = e.parameter.url; 
     var sheet = getSheet("google home api");
    sheet.getRange(2,1,1,1).setValues([[url]]); // getRange(開始行、開始列、行数、列数)
    return "ok";
  }
} 

function request(text) {
  try {
   var sheet = getSheet("google home api");
   var url = sheet.getRange(2,1,1,1).getValues()[0][0] + '/google-home-notifier';
    var urlFetchOption = { 
        'method' : 'post',     
        'contentType' : 'application/x-www-form-urlencoded', 
        'payload' : { 'text' : text}  
    }; 
 
    var response = UrlFetchApp.fetch(url, urlFetchOption); 
    return response; 
  } catch (e) {
    var sheet = getSheet("gaslog");
    sheet.appendRow([e]);
  }
}

function getSheetApp() {
  return SpreadsheetApp.openById("<NGROKのURLを保存しているシートのID>");
}

function getSheet(name) {
  var sheetApp  = getSheetApp();
  var sheet     = sheetApp.getSheetByName(name);
  return sheet;
}

このGASのスクリプトスクリプトエディタの「公開>ウェブアプリケーションとして導入…」から公開しておきます。AAA...BBB...となっているトークンはそれぞれ、SlackのWebhookとGoogle Home側のネットワークに自前で立てたサーバーからのトークンを設定してください。

Google Homeでのテキストの受け取り

今回はGoogle Homeと同一のネットワークにいるラズパイにソースコードを置き作成しました。google-home-notifierとngrokが便利すぎますね。

var express = require('express');
var googlehome = require('google-home-notifier');
var ngrok = require('ngrok');
var bodyParser = require('body-parser');
var app = express();
const serverPort = 8091; // default port

var deviceName = 'Google Home';
var ip = 'XXX.XXX.XXX.XXX'; // default IP

googlehome.device(deviceName, 'ja').accent('ja').ip(ip); // 日本語で喋ってもらうために必要

var urlencodedParser = bodyParser.urlencoded({ extended: false });

app.post('/google-home-notifier', urlencodedParser, function (req, res) {

  if (!req.body) return res.sendStatus(400)
  console.log(req.body);

  var text = req.body.text;

  if (req.query.ip) {
     ip = req.query.ip;
  }

  var language = 'pl'; // default language code
  if (req.query.language) {
    language;
  }

  googlehome.ip(ip, language);

  if (text){
    try {
      googlehome.notify(text, function(notifyRes) {
        console.log(notifyRes);
        res.send(deviceName + ' will say: ' + text + '\n');
      });
    } catch(err) {
      console.log(err);
      res.sendStatus(500);
      res.send(err);
    }
  }else{
    res.send('Please GET "text=Hello Google Home"');
  }
})

app.listen(serverPort, function () {
  ngrok.connect(serverPort, function (err, url) {
    // GASにngrokのURLを通知する
    request.post('<GASの公開URL>', {form:{token:"BBBBBB...", url: "url"}})
  });
})

まとめ

駆け足でしたが、Google HomeとAkerunを連携する方法を紹介してみました。 実装上はSlackを経由する必要はない例でしたが、Slackにも通知した上でGoogle Homeにも喋って欲しいケースはあるかなと思いこちらの方法を採用しました。手順は多いですが、段階を踏むのでデバッグも便利です。

弊社ではKitayo...じゃなかった、receptionistを使っていて、Slackで受付情報をもらっているので、合わせて執務室内のGoogle Homeに音声で教えてもらうと便利なのかなと思っています(音声でそれを聞いた結果誰がどう受付対応するのかという話が別でありますが)。

ラズパイや不要なPCがあれば、任意のテキストを喋るGoogle Home APIを簡単につくれるので、色々な連携には便利なのかなと思いまいた。 皆様も是非やってみてください。

告知

弊社ではエンジニアを募集しています!

www.wantedly.com