R筋

プログラミング、金融、育児

Raspberry piでGoogle Homeに話をさせていたら気づいた大切なこと

目次

今回作ったのはこれだ


ずっとほしいなぁと思っていたんだけど、いよいよ禁断症状が出てきて会社帰りに秋葉原で買ってしまったraspberry pi zero!!このLINEに書いた内容を喋らせるヤツ、ブログでいくつか開発している記事を仕事中に見るにつけて、やりたくてやりたくて仕事が手につかなかったもんだから仕方がないことですね。

rassberry pi初期設定

初心者なので色々なものが入っているこちらのスターターキットを買いました。
Raspberry Pi Zero W スターターキット--在庫限り - スイッチサイエンス
まずはセッティング。スターターキットに色々と変換アダプタが入っているので簡単にはじめられる。電源アダプタを入れると自動的に起動してしまうので、他の接続を先に済ませて最後に電源をつなげよう。
f:id:anpontan382:20180302233900p:plain
また、本来はmicroSDの中に公式サイトからダウンロードしたOSを入れてから差さないといけないのだが、スタータキットにはすでにOSがmicroSDにコピー済みのため差し込むだけで準備完了だ。
f:id:anpontan382:20180302234515p:plain
電源を入れて少し待つとこんなかんじの起動画面になる。
OSが起動したら、いくつかの初期設定を行う。amazon ultimatedで無料で読めるので、この本を参考にした。

設定内容は次の通り。
wi-fi接続
SSH、I2Cを使用可
③ログインパスワードの変更
タイムゾーン
これだけで、ネットサーフィンもできる普通のPCとして使用できる状態になる。だが、512MBのメモリではネットサーフィンなどはめちゃくちゃ重たく、実用性はほぼないだろう。基本的に遠隔でログインして操作することになる。
そのために必要な
SSHの設定
FTPサーバの設定
IPアドレスの固定
の作業があるがこれも上記書籍を参考にした。
加えて、LAN外からもアクセスできるようネットワークの設定も変更した。
anpontan382.hatenablog.com
外部からのアクセスにするため、
①ポート番号をデフォルトから変更
②公開鍵認証
を設定している。
これによって、普段使っているwindowsPCから、teratermFFFTPでrasberry piを操作できるようになった。
f:id:anpontan382:20180303002812p:plain

google-home-notifierの設定

続いて、googleHomeに喋らせるために必要なパッケージをインストールする。
コマンドは、こちらを参考にした。
GoogleHomeスピーカーに外部からプッシュして自発的に話してもらいます - Qiita
必要なパッケージは次の通り
・node.js→javascriptを実行する環境
・npm→node.jsで使うパッケージを管理するツール
・nvm→node.jsのバージョンを管理するツール
google-home-notifier→javascriptgoogle homeを動かすためのパッケージ

ハマった場所をメモしておこう。
google-home-notifierのインストールで次のエラーが出た。

pi@raspberrypi:~/google-home-notifier $ npm install -g google-home-notifier
npm WARN package.json google-home-notifier@1.2.0 No repository field.
\
> mdns@2.3.4 install /home/pi/google-home-notifier/node_modules/mdns
> node-gyp rebuild

make: Entering directory '/home/pi/google-home-notifier/node_modules/mdns/build'
  CXX(target) Release/obj.target/dns_sd_bindings/src/dns_sd.o
In file included from ../src/mdns.hpp:12:0,
                 from ../src/dns_sd.cpp:1:
../node_modules/nan/nan.h:324:47: error: ‘REPLACE_INVALID_UTF8’ is not a member of ‘v8::String ’
   static const unsigned kReplaceInvalidUtf8 = v8::String::REPLACE_INVALID_UTF8;
…

この解決方法は、こちらあった。
Raspbianでのnpm install leveldownではまったメモ - Qiita
nodeのバージョンが問題とのことで、nvmでバージョンを変えようとしたが、nvmもエラーが出る。(
gitを使ったnvm(node version manager)のインストールから複数バージョンのnode.jsインストール及びその切替え手順のご紹介です。
これによると、nvmは最初無効化されているため、有効化するコマンド

source ~/.nvm/nvm.sh

が必要だそう。

そんなこんなで、必要なパッケージが揃った。先程の記事を参考にテストコードを記載。

const googlehome = require('google-home-notifier');
const language = 'ja';
googlehome.device("Google-Home", language);
googlehome.ip("192.168.100.112");
googlehome.notify('わっちゃん、おはよう', function(res) {
  console.log(res);
});

わっちゃんというのは息子の名前である。これを実行してみると、

$ node test.js
events.js:183
throw er; // Unhandled 'error' event
^
Error: getaddrinfo -3008
…

残念まだエラー。
npm|yarnで怒られたエラー集まとめ。WARN[deprecated,unmet dependency,peerDependencies,EPEERINVALID,engine]ERR![missing,invalid],throw er; // Unhandled 'error' eventの解決方法。(2019/3/8更新) - Qiita
どうやら複数プロセスが動いていると起こるみたい。

$ ps aux | grep node
pi 20091 2.6 7.2 124928 32236 pts/0 Tl 21:23 0:05 node
pi@raspberrypi:~/googlehome $ sudo kill -9 20091

としたら、喋りだした!

cronで実行

ついでに「おはよう」なので毎朝7時に喋るようにセットしておくことにした。cronという定時に自動実行する機能に登録をする。
決まった時間に処理する | Make.
ここを参考にcronをスタートさせ、

$ crontab -e

へ次のコマンドを登録。

*/2 * * * * /home/pi/.nvm/versions/node/v8.9.4/bin/node /home/pi/googlehome/ohayo.js

・ 「****」とすると1分毎に実行だが、タイミングによってはうまくいかないこともあるため、「*/2 * * * *」として2分毎の実行登録がいいそうだ。
・実行させるnodeはフルパスにしておく。
、、、しかしエラー、ログを見てみる。

$ cat /var/log/syslog
Feb 28 22:22:01 raspberrypi CRON[20756]: (CRON) info (No MTA installed, discarding output)

システムログのエラーでググると同じ事象が見つかった。
Raspberry Piでcronを使った時の話し - Qiita
cronは実行されるとメールが飛ぶ仕組みであるためpostfixを入れておかないと行けないようだ。デフォでは「var/mail」に届く。
これでcronは解決。「00 7 * * * 」とすれば毎日7時に「わっちゃんおはよー」とgoogleHomeが話しかけるようになったとさ。

LINE通知から実行

そして本来やりたかったLINE通知から喋らせるヤツはこのふたつを参考にした。
Google Homeで子供の朝支度を促してみる - Qiita
Google HomeにLINEのメッセージを読み上げさせる(LINE BOT+Webhook+Firebase+Node.js) - メガロドンblog
データの流れはこんな感じ。
f:id:anpontan382:20180303091057p:plain
①LINE messageAPI → ②firebase → ③rassberry pi → ④google home

まず②のfirebaseへの登録を行う。上記記事を参考に、googleアカウントでログインし、googlehome用のデータベースを作成した。
firebaseっていうのは、webアプリなどを作る際に役立つ便利な機能が色々とあるサービス。従来自分でサーバを構築しないと出来なかったことが、簡単にできるようになる。今回はこのリアルタイムデータベース機能で、LINEからの通知を受け取る。

続いて①のLINE messageAPIへ登録する。これはお店などでよくあるBOTを作れるサービスだが、相手から通知を受けた時に、それに対応できるようにもなっており、webhockにデータを送ることができる。これをfirebase宛に設定することで、LINEの通知をfirebaseに届けることができる。

最後に③のrassberry piでfirebaseの更新を受け取れるようにする。
firebaseのパッケージをインストール。

npm install firebase

firebaseの更新を監視し、更新があればgoogleHomeに送るスクリプトを作ります。

const googlehome = require('google-home-notifier');
const language = 'ja';
googlehome.device("Google-Home", language);
googlehome.ip("192.168.100.112");

var firebase = require("firebase");
var config = {
  apiKey: "********",
  authDomain: "***********.frebaseapp.com",
  databaseURL: "https://********.firebaseio.com",
  projectId: "******",
  storageBucket: "",
  messagingSenderId: "*************"
};
//firebaseの設定画面で確認

firebase.initializeApp(config);
var db = firebase.database()
var receivedlineRef = db.ref( '/line/mes');

receivedlineRef.on("child_added", function(snap) {
  var linemessage = snap.val();
  snap.ref.remove(); //Delete child in firebase
  var textmain = linemessage.events[0].message.text;
  googlehome.notify(textmain, function(res) {
    console.log(textmain);
  });

nohup~&で実行すると、SSHを切断しても実行し続ける。

nohup node firebase.js &

完成!

今後の展開

なんだかんだで手間がかかったが、使ってみると色々アイデアが出てきてワクワクしてくる。
親が言っても聞かないときに、こっそりLINEで「わっちゃんもう寝ようね」と送って、googleHomeに話させる。「ほら天才googleHome様もそういってるから寝ようよ」みたいな感じで、しつけを代わりにやってもらうこともできる。
他にも、現在は日本語を読み上げる設定になっているが、英語を話させるのも楽しそう。LINEには翻訳BOTがあるので、親が考えた日本語を英語に翻訳させてgoogleHomeに話させれば親の英語力によらず英語教育が可能だ。
LINE以外にもfirebaseの更新でgoogleHomeを話させることができるわけだから、WEBをスクレイピングして「今日はひな祭りの日で、雛人形を飾ります」みたいな教養が取れれば、親の教養力によらず教養ある人間が育つだろう。

本当の今後の展開

いやはや機械が仕事を奪うってよく言われているが、これをやっていると子育ても奪われかねない。
いやまて、すでに僕は「息子に楽しんでもらうぞ~」という大義名分のもと、夜な夜なパソコンに齧りついてプログラムを書いているわけだが、すでに機械に子育ての機会を奪われている状況ではないか。
google Homeが自分から話をする機能はいずれgoogleが提供してくれるだろう。僕がわざわざしなくてもいいのではないか。
僕がgoogle Home開発をしている間、妻は祖父母に近況報告の手紙を書いていた。
f:id:anpontan382:20180303095210j:plain
人間ができること、すべきことむしろこれなのではないか!!

真理に到達した僕は、rassberry piからgoogle Homeを爆発させるコマンドを打ち込み、エンターキーをズッターン!と叩き、燃え上がるgoogle Homeを背に、寝ている息子のもとへ向かった(嘘)

でもホントは僕もわかっている。もう少し日々の子育てや家事をしたほうが、家族みんなにとって良いし、他にも6月にある重要な資格の勉強しなきゃいけないってこと。プログラムやブログを書いている場合じゃないことは確かなんだってこと。