コモノポリタン

コモノ、デジモノが好きなKomonopolitan住民 (はてなダイアリーからの引っ越しです)

【Home AssistantでDIY Smart Home】Alexaを喋らせよう

【Home Assistant(Hass.io)】
Alexaに雨の降り始めを報告させる

「Home Assistant(Hass.io)でホームオートメーション 再起動!」シリーズです。

 雨降りセンサーがあるのに雨の降り始めは教えてくれない、そんな残念なスマートホームでしたが、携帯へのメッセージは飛ぶようになりました(前の記事)。一歩踏み込んで「家にいるときは話しかけてくれれば良いのに」と思い、ちょっとごにょごにょしてみました。

 家中にあるGoogle Homeバイスを喋らせるのが一番良いのですが、こいつはメインのネットワークに接続されており、Home Assistantとはちょっと遠い関係にあります。むむ。
 そうだ、一人寂し気に佇むAmazon Echoちゃんを活用してみよう!
f:id:maky_Ba:20220131022728j:plain:w250

この記事の前提条件
Home Assistant 2021.12.10
HassOS 7.2
Server Raspberry Pi 4(2GB)

 上記バージョンを前提とした手順です。 (最新版では動かないこともあるかもしれませんが、私が使っている限り、備忘録を兼ねて最新化してゆきたいとは思っています)

1. 準備(Alexaの引越)

(追記:ここ不要。Alexa-Remote-ControlはEchoと同じネットワークに居る必要ありません。google-home-notifierのイメージを引きずっていました。)
 まずはAlexaをHome Assistantの住んでいるネットワークに引越しさせます。
 これは私の環境特有の準備です。うちのネットワークは、ふつうのLANとスマートホーム用のLANの2系統に分離されています。Google Home系はテレビとかとも連携しているので普通のLAN側にいます。Amazon Echoちゃんも普通のLAN側にいますが、やることと言ったらAmazonから荷物が来た時に黄色に光るぐらいで存在感がまったくありません(ごめんAlexaが悪いわけではない。良い子です)。

 接続ネットワークの変更は、Alexaアプリを使います。詳細はほぼ初期設定と同じかな。

2. Raspberry Pi Zero Wのセットアップ

 Alexaを喋らせるのにoathtoolなど(場合によってはjqも)をインストールする必要があるので、独自環境をRaspberry Pi Zero Wで作ります。
(Home Assistantサーバー上で独自Pythonスクリプトを実行させる環境(AppDaemonとかPyscriptとか)を流用する手もありそうですが、まだうまく使いこなせていないので、いずれ、ですかね)

2.1. Raspberry OSの導入

 まあ、今までと同じですが、RaspiOSのメジャーバージョンがあがりBullseyeになりました。(今回は一気に上がらず、今までのBusterはRaspberry Pi OS (Legacy)として併存していますね。)

下記から「Raspberry Pi Imager」をダウンロードしてOSのMicroSDカードイメージを作成するのが簡単です。OSのダウンロードもやってくれます。
www.raspberrypi.com

  1. Raspberry Pi Imager」を起動して「Choose OS」では、[Raspberry Pi OS (other)]-->[Raspberry Pi OS Lite (32bit)]を選択。これがBullseyeのGUI無し版です。
  2. そのmicroSDをもう一度PCに刺し直して、そのルートディレクトリ(ドライブ名:boot)にsshという空ファイルを作る(Windowsならエクスプローラで右ボタンでtextファイルを作り、拡張子txtを削除。Linuxならtouchコマンドかな)。これで再起動時にsshで接続できるようになる。
  3. 無線LANを使えるように、microSDのルートディレクトリ(ドライブ名:boot)にwpa_supplicant.confを作成。
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
  ssid="<接続する無線LANのSSID>"
  psk="<暗号化キー>"
}

 MicroSDカードをRaspberry Pi Zero Wに挿して起動しておいて、どこからか(Home AssistantのTerminalからでも)sshでこのRaspberry Pi Zero Wに接続。その後、$ sudo raspi-configで設定モードに入り、piユーザのパスワード変更やLocale, Time zone, SSH onなどの設定をしておきましょう。

2.2. 必要パッケージの導入

 Alexaをコマンドラインから喋らせるために、まずはRaspberry Pi Zero Wを最新にして、次にalexa接続の2段階認証で必要となるoathtoolをあらかじめインストールしておきます。

$ sudo su
# apt-get update -y
# apt-get upgrade -y
# apt-get autoremove
# apt-get clean
# apt-get install -y oathtool 

2.3. sshでのリモート接続の準備

 Home Assistant側から今回作ったRaspberry Pi Zero側(リモート側)にsshで接続する準備をします。
 キーペアはssh-keygenなどで作成済みだと下記フォルダとかに格納されたりしてるかと思います。

$ ls -la ~/.ssh/
drwx------   2 root   root     4096 Jan 29 20:25 .
drwxr-xr-x   3 root   root     4096 Jan 25 18.35 ..
-rw-------   1 root   root     2590 Jan 29 20:37 id_rsa
-rw-------   1 root   root     2590 Jan 29 20:37 id_rsa.pub

 まずはリモート側に公開鍵をコピーします。

$ ssh-copy-id -i ~/.ssh/id_rsa.pub pi@<今回作ったRaspberryPiZeroWのIPアドレス>

 次にHome Assistantのcommand lineインテグレーションで使えるようにid_rsaを/config/.ssh/の下にコピーします(←これが肝心のようです。結構ハマりました。)。

$ cp ~/.ssh/id_rsa /config/.ssh/

 公開鍵認証でのssh接続テストをしてみます。

$ cd /config
$ ssh -i ./.ssh/id_rsa -o 'StrictHostKeyCheck=no' pi@<今回作ったRaspberryPiZeroWのIPアドレス>

2.4. Alexa-Remote-Controlの導入

 Alexaをコマンドラインからリモートコントロール(「喋らせる」を含む)する方法は下記にあります。
github.com

 このなかのalexa_remote_control_plain.shJSON処理のためのjqライブラリ不要なのでこちらを使います。*1
 このシェルスクリプトを含む全体をwgetとかでGitHubからダウンロードする、という手もありますが、高々ファイル1個なので、RAW表示したalexa_remote_control_plain.shテキストエディタなどにコピーしてalexa_remote_control_plain.shを手に入れればよいかと。
 Raspberry Pi Zero Wの適当なディレクトリ(/home/pi/alexa_remote_control/とか)にコピーしてエディタ(nanoとか)で開き、下記のあたりにAmazonアカウントの情報に従って記入しておきます。

(途中)
SET_EMAL=<amazonアカウントID>
SET_PASSWORD=<amazonアカウントのパスワード>(直書きはいやですね)
SET_MFA_SECRET=<2段階認証のキー:1234 5678 ...の様な4桁x13個>
SET_LANGUAGE='jp-JP'
SET_TTS_LOCALE='jp-JP'
SET_AMAZON='amazon.co.jp'
SET_ALEXA='alexa.amazon.co.jp'

SET_MFA_SECRETのところですが、「アカウント&リスト」⇒「ログインとセキュリティ」⇒「2段階認証の設定:」[編集]⇒「新しいアプリを追加」⇒「パスワードをスキャンできませんか?」をクリックすると2段階認証のキーが表示されます。

 忘れずにalexa_remote_control_plain.shシェルスクリプトパーミッションを実行可能にしておきます。

$ chmod 755 alexa_remote_control_plain.sh

 お試しに喋らせてみましょう。

$ ./alexa_remote_control_plain.sh -e "speak:おはようございます"

 しゃべりましたか?
 うまくいけば「おはようございます」といつものAlexaの声で発声してくれます。*2

3. Home Assistantの設定

3.1. Alexaおしゃべりサービスの設定

 まずは、今回作ったRaspberry Pi Zero W上にあるAlexaを喋らせるシェルスクリプトをサービスとしてHome Assistantで呼び出せるようにします。

(前略)
shell_command:
  speak_alexa_start_raining: ssh -i /config/.ssh/id_rsa -o 'StrictHostKeyChecking=no' pi@<Raspberry Pi Zero Wのホスト名もしくはIPアドレス> '/home/pi/alexa_remote_control/alexa_remote_control_plain.sh -e "speak:雨が降り始めたかもしれません。"'
(後略)

 (セキュリティ上の理由だと思いますが、/config/以下しか見えない・操作できないようです。コンソール上から動いているのに、サービス化させると動かないという状態にハマりました。真面目にドキュメント読んでいないので他にもトラップありそう・・・)

3.2. 通知の設定

 以前の記事「【Home AssistantでDIY Smart Home】雨が降ったらお知らせ - コモノポリタン」でアプリに降雨の通知を行いましたが、ほぼ同じオートメーションを作ります。今回は「洗濯物の取り込み促進」を主眼に、昼間だけ通知を行うよう条件を追加します。夜にいきなりAlexaが話し出すと「どきっ」としますからね。

<オートメーションの設定>

  • 名前:(適当に、Notify start raining by Alexaとか)
  • モード:シングル(デフォルト)
  • オートメーションの有効化/無効化:オン

トリガー:

  • トリガーの種類:状態
  • エンティティ:binary_sensor_xiaomi_door_window_XX_contact(雨降りセンサーを指定)
  • 変化後:off
  • 持続時間:00:00:00(←これを設定すれば感度が調整できるかも…)

条件:

  • 条件の種類:時間
  • 定刻 or 日付/時刻ヘルパーの値:定刻
  • 後:7:00
  • 定刻 or 日付/時刻ヘルパーの値:定刻
  • 前:18:00
  • 月曜日:オン
  • 日曜日:オン

アクション:

  • サービスの種類: サービスの呼び出し
  • サービス:shell_command.alexa_notify_start_raining

 このようにオートメーションを設定すると、降雨センサーが水滴を感知する(=センサーがoffになる)してかつ昼間(7:00~18:00 ※)の間だけ、Alexaが「雨が降り始めたかもしれません。」という弱気なメッセージを読み上げるようになります。
 ※:より正確(?)には「条件の種類:太陽」「後:日の出」「前:日の入り」とすると良いかもしれませんね。オフセット1時間とか設定するとなお良しかも、ですが。

4. おわりに

 テストしてみると、センサーが反応してから20~30秒ぐらいかかってからAlexaが喋ります。Alexaのログイン処理がそのぐらいかかっている様子。まあ、雨降り通知とかの自発発声には問題ないレベルですね。
 ただ何かの答えを発生させようという場合(例えば「家の鍵は全部しまっているか?」とかへの応答発声)、そのタイムラグはちょっとあれかもしれませんね。いろいろ考えることありますねぇ。

maky-ba.hatenablog.com

*1:とか言って、ああ、しばらく時間をかけているうちに「非推奨(DEPRECATED)」になっちゃった…。通常のログインが出来なくなるころに、またがんばりますか…。

*2:alexa_remote_controlは、男声・女声の切り替えや、囁き発声などのAlexaが持つサービスに対応しているのですが、うちの環境は設定が足りないせいか「スキルがありません」的な発言をしてうまくいきません。またいろいろ試してみないと、ですね。