【未経験向け】CCNA(200-301)とは? NW未経験が1ヶ月で合格した際に使用した魔法の学習教材、サイトを紹介!!!

Slack の通知を検知して 投稿内容をGoogle Home に喋らせる

Google Home/Next

会社でシステムアラート受付用のSlackチャンネルがあるのですが、そこにアラートが投稿されると電話が掛かってくる仕掛けとなっているのですが、以下の問題点があります。

  • 全てのアラートが通知されるわけではない
  • 寝落ちした時にスマフォの電源が切れてると通知に気づけない
  • そもそも電話の着信音だけで起きれる自信がない

そこで、Slackへの投稿をトリガーに我が家の Google Home 君に通知内容を喋らせるようにしたいのです。

Google Home は常に起動しているので、スマフォの電源が落ちてる時にアラートが鳴っても気づけるようになります。

本記事では、Slackの投稿をトリガーに自宅のGoogle Home に投稿内容を喋らせるシステムの構築手順を公開します。

スポンサーリンク

概要

目的

  • Slackの通知を検知して、自宅のGoogle Home Miniに投稿内容を喋らせる

利用サービス

  • Slack
  • Google Home Mini
  • google-home-notifier(Github)
  • Raspberry Pi 4b
    ※ 最初 Zero W でやろうとしたが失敗
    (ARMv6だとNode入れるのが困難なのでラズパイを利用するならARMv7以上の製品がオススメ!)
  • Google App Script(GAS)

構成

  1. Slackへの投稿をGASでフックして、google-home-notifierのURL(ngrok)へ処理を飛ばす。
  2. google-home-notifierからGoogle Home Miniへ読み上げ処理をPush。

作業工程

  1. Raspberry Piで Node, Pythonが使えるように設定
  2. Raspberry Pi へ google-home-notifier をインストール & セットアップ
  3. Slackで Outgoing Webhook の設定
  4. Google App Script(GAS)でSlackからの通知をフックさせるスクリプトを作成

参考文献

手順

Raspberry Pi 側の設定

google-home-notifier(Github)のREADME.mdに使用方法が記載されおります。
があくまでHowToであって使用手順ではないので、本記事で改めて使用手順を展開させて頂きます。

google-home-notifier はNode.jsで動作しますので、Raspberry Pi にてNode.jsとnpmのインストールを行います。
※ 注意 –> RaspberryPi Zero(ARMv6)でやると失敗します

## nodeのインストール
$ sudo apt-get update
$ sudo apt-get install -y nodejs npm
$ sudo npm cache clean
$ sudo npm install npm n -g
$ sudo n stable

## バージョン確認
$ node -v
$ npm -v

当たり前ですが、npmの利用にPythonが必要になります。
RaspberryPiだとデフォルトで入ってるはずなのでインストール手順は割愛しますが、利用するラズパイにPython(できれば3.x以上)がインストールされていることを確認しておきましょう。

## Pythonのバージョン確認
$ python --version

事前にgoogle-home-notifierの動作に必要なパッケージをインストールします。
その後、google-home-notifier(Gitリポジトリ)をダウンロードし、落としてきたディレクトリにてnpmを使用したインストールを行います。

## 必要パッケージのインストール
$ sudo apt install libnss-mdns libavahi-compat-libdnssd-dev

## google-home-notifier のインストール
$ git clone https://github.com/noelportugal/google-home-notifier
$ cd google-home-notifier
$ npm install

インストールが確認できたら、google-home-notifierの設定を行います。
修正をかけるファイルは下記の4つ

  • browser.js
  • google-home-notifier.js
  • package.json
  • example.js

browser.jsを修正します。
こちらの手順は公式リポジトリのREADME.mdにも記載されています。

$ vi node_modules/mdns/lib/browser.js
-Browser.defaultResolverSequence = [
-  rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo()
-, rst.makeAddressesUnique()
-];
+Browser.defaultResolverSequence = [
+  rst.DNSServiceResolve(), 'DNSServiceGetAddrInfo' in dns_sd ? rst.DNSServiceGetAddrInfo() : rst.getaddrinfo({families:[4]})
+, rst.makeAddressesUnique()
+];

google-home-notifier.jsの修正を行います。
ここではGoogle Homeのデバイス情報や言語設定に変更を加えます。

var Client = require('castv2-client').Client;
var DefaultMediaReceiver = require('castv2-client').DefaultMediaReceiver;
var mdns = require('mdns');
var browser = mdns.createBrowser(mdns.tcp('googlecast'));
var deviceAddress = '192.168.xx.xx'; // Google Home のIPアドレスに修正する
var language;

var device = function(name, lang = 'ja') { // "ja"に修正する
    device = name;
    language = lang;
    return this;
};

var ip = function(ip, lang = 'ja') { // "ja"に修正する
  deviceAddress = ip;
  language = lang;
  return this;
}

var googletts = require('google-tts-api');
var googlettsaccent = 'ja'; // "ja"に修正する
var accent = function(accent) {
  googlettsaccent = accent;
  return this;
}
~~~ 以下略 ~~~

package.jsonの修正を行います。
修正するポイントは2つ、ngrokのバージョンgoogle-tts-apiのバージョンです。

▽ ngrokのバージョンについて
google-home-notifier単体ではローカル参照用のURLしか生成してくれません。
なので外部連携には、ngrokが生成したURLを利用します。

デフォルトではインストールするngrokのバージョンが、2.3.0 と古く、このままではエラーを吐いてしまうので、3.2.7 にバージョンを上げてやります。

▽ google-tts-apiのバージョンについて
GoogleのText-To-Speech(TTS)のAPIの仕様が頻繁に更新されます。
この影響によりgoogle-home-notifierの実行時にAPIエラーがでてしまいますので、バージョンを上げてやる必要があります。

デフォルトのバージョンが 0.0.2 なので、0.0.6 にあげます。
※ 2022/05/08時点では、バージョン0.0.6での動作を確認しています

{
  "name": "google-home-notifier",
  "version": "1.2.0",
  "description": "",
  "main": "google-home-notifier.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Noel Portugal",
  "keywords": [
    "google home",
    "notifications",
    "notifier"
  ],
  "license": "MIT",
  "dependencies": {
    "body-parser": "^1.15.2",
    "castv2-client": "^1.1.2",
    "express": "^4.14.0",
    "google-tts-api": "0.0.6", //「0.0.2」-->「0.0.6」へ修正
    "mdns": "^2.3.3",
    "ngrok": "^3.2.7" //「2.3.0」-->「3.2.7」へ修正
  }
}

example.jsの修正を行います。
こちらは設定ファイルではなく、google-home-notifierが用意してくれたサンプルスクリプトになります。
Google Homeとの連携は基本的にこのスクリプトを使用する形になります。

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 = '192.168.xx.xx'; //ここにGoogle Homeの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 = 'ja'; // "ja"に修正
  if (req.query.language) {
    language;
  }

  googlehome.ip(ip, language);
  googlehome.device(deviceName,language);

  if (text){
    try {
      if (text.startsWith('http')){
        var mp3_url = text;
        googlehome.play(mp3_url, function(notifyRes) {
          console.log(notifyRes);
          res.send(deviceName + ' will play sound from url: ' + mp3_url + '\n');
        });
      } else {
        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.get('/google-home-notifier', function (req, res) {

  console.log(req.query);

  var text = req.query.text;

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

  var language = 'ja'; // "ja"に修正
  if (req.query.language) {
    language;
  }

  googlehome.ip(ip, language);
  googlehome.device(deviceName,language);

  if (text) {
    try {
      if (text.startsWith('http')){
        var mp3_url = text;
        googlehome.play(mp3_url, function(notifyRes) {
          console.log(notifyRes);
          res.send(deviceName + ' will play sound from url: ' + mp3_url + '\n');
        });
      } else {
        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"');
  }
})

// ngrokのバージョンアップに伴い、下記コードを更新する必要がある
-app.listen(serverPort, function () {
-  ngrok.connect(serverPort, function (err, url) {
+app.listen(serverPort, async function () {
+  const url = await ngrok.connect(serverPort);
    console.log('Endpoints:');
    console.log('    http://' + ip + ':' + serverPort + '/google-home-notifier');
    console.log('    ' + url + '/google-home-notifier');
    console.log('GET example:');
    console.log('curl -X GET ' + url + '/google-home-notifier?text=Hello+Google+Home');
        console.log('POST example:');
        console.log('curl -X POST -d "text=Hello Google Home" ' + url + '/google-home-notifier');
-})

以上でRaspberry Pi側での設定は全て完了となります。
正しく設定できた動作確認してみましょう。

先程変更を加えた、example.jsを実行し、出力されたngrokのURLへPOSTデータを送信し、Google Homeがそのテキストを無事読み上げれば動作確認は完了となります。

## Google HomeへのPush用のURLを生成
$ node example.js
Endpoints:
    http://192.168.xx.xx:xxxx/google-home-notifier
    https://<ハッシュ値>.ngrok.io/google-home-notifier
GET example:
curl -X GET https://<ハッシュ値>.ngrok.io/google-home-notifier?text=Hello+Google+Home
POST example:
curl -X POST -d "text=Hello Google Home" https://<ハッシュ値>.ngrok.io/google-home-notifier

## curlコマンドにてPOSTデータの送信
$ curl -X POST -d "text=Hello Google Home" https://<ハッシュ値>.ngrok.io/google-home-notifier

Google App Script 側の設定

ローカルでの設定が完了したので続いて、SlackとRaspberry Piを繋げるGoogle App Script(GAS)を作成します。

ベースコードを展開しますので、下記に従いコードを修正して下さい。
・Token = 後述で作成するSlackのOutgoing Webhookのトークンを指定します
・url = google-home-notifierを起動した際に表示されるngrokのURLを指定します

function doPost(e) {
  // Slackのトークンを指定
  var token = "<TokenId>"; 
  if (token != e.parameter.token) { 
    return; 
  } 

  // 投稿内容(テキスト)を取得
  var text = e.parameter.text
  text = 'Slackの新着メッセージです' + text;

  return request(text); 
}

function request(text) { 
    // ngrokのUrlを指定
    var url = 'https://********.ngrok.io/google-home-notifier'; 
    var urlFetchOption = { 
        'method' : 'post',     
        'contentType' : 'application/x-www-form-urlencoded', 
        'payload' : { 'text' : text}  
    }; 

    var response = UrlFetchApp.fetch(url, urlFetchOption); 
    return response; 
}

設定したら「公開」⇒「ウェブアプリケーションとして導入」を選択し、「アプリケーションにアクセスできるユーザー」を「全員(匿名ユーザーを含む)」に設定します。

これで外部から実行できるようになります。

Slack 側の設定

最後に肝心のSlack側での設定を行います。

手順1:Slackを開き、画面右上の「マイアイコン」をクリックし、プルダウンから「環境設定」をクリックします。

手順2:左ペイン「連携アカウント」–>「Webアプリ管理ページ」をクリックします。

手順3:Slackのアプリ管理ページが開きますので、上部検索バーにて、「Outgoing WebHook」と検索します。

手順4:Outgoing WebHookを開いたら、「Slackへ追加」をクリックします。

手順5:各項目に従い、設定値を入力します。設定完了後、画面下部「設定を保存する」をクリックします。

  • インテグレーションの設定
  • チャンネル –> 通知を受け取るチャンネルを指定します
  • 引き金となる言葉 –> 特定のワードから始まる投稿内容を通知対象にする設定です。全ての投稿を検知したい場合は未記入で大丈夫です
  • URL –> GASのWebリンクのURLを貼り付けます
  • トークン –> 内容をコピーしてGASのTokenに指定します
  • 説明ラベル –> 任意の説明を入力します
  • 名前をカスタマイズ –> 任意の説明を入力します

以上でSlackの設定は完了となります。

最後に動作確認として対象のチャンネルでメッセージを投稿してみましょう。
ここまで問題なく設定できていれば、無事Google Homeが投稿内容を読み上げてくれると思います。

まとめ & 課題

いかがだったでしょうか。
無事本記事の手順を頼りに通知システムが構築できたでしょうか。

もし、上手く動作しない等でお悩みでしたら、コメント頂ければなんでもご相談に乗りますので、本ブログのお問い合わせページよりご連絡下さい。

また、本通知システムを常時稼働するに辺り以下の課題があります。

  • ngrokの生成するURLが可変なので、URLの生成の度にGASを更新しなくてはいけない

上記課題に関する記事を後日執筆しようかと思いますので、そちらも併せてご覧頂けると幸いです。

コメント

タイトルとURLをコピーしました