Alexaから音声でPCを操作

2022年2月20日

はじめに

先日やっとEcho Dot 第3世代を買ったはいいものの、このままでは地味なオブジェになりそうです。
きっと興味本位で買って同じオチになっている仲間は多いはず。
でもライトやエアコンだけじゃなく、パソコンもAlexaから操作できたら便利な気がしません?

外部のサービスを使えば導入が楽で汎用性も高そうですがアカウントが必要だったり、このあたりの技術は移り変わりが激しいのでいつの間にか使えなくなりそう。。。
調べてみたらNode-REDを使えば(Alexa以外は)ローカルだけで完結していつまでも使える環境構築を実現できそうなので試してみました。

環境はWindows10 64bit、特に記載がない箇所はドキュメント通り&デフォルト設定で行っています

1.Node-RED環境の準備

ⅰ.インストール

Node-RED User Group Japanのドキュメント『Windowsで実行する』を参考に、音声操作したいパソコンへインストールします。
常用する予定の方は、パソコン起動時に自動実行させるところまでやっておいてもいいかも。

ついでにファイアウォールの設定も行います。
Node-REDの実行前に以下のコマンドを管理者として実行します。
1880:Node-REDで使用
80:Echo Dot からのアクセスで使用⇒8111へポートフォワーディング
8111:Node-RED内で作成した仮想デバイスで使用

netsh advfirewall firewall add rule name=”node.js” dir=in action=allow protocol=TCP localport=1880
netsh advfirewall firewall add rule name=”node.js” dir=in action=allow protocol=TCP localport=80
netsh advfirewall firewall add rule name=”node.js” dir=in action=allow protocol=TCP localport=8111
netsh interface portproxy add v4tov4 listenport=80 listenaddr=0.0.0.0 connectport=8111 connectaddress=127.0.0.1

node-redを実行して、ここまで表示されれば起動成功

20 Feb 11:56:02 – [info] Server now running at http://127.0.0.1:1880/
20 Feb 11:56:02 – [info] Starting flows
20 Feb 11:56:03 – [info] Started flows

ⅱ.Node-REDのエディタ画面を開く

ブラウザでhttp://localhost:1880/にアクセスしてエディタ画面を開きます。

ⅲ.ノードの追加

エディタ画面右上の を押して、『パレットの管理』を開きます。

タブ『ノードを追加』を開いて”node-red-contrib-amazon-echo”を検索。
ヒットした中から上記と全く同じ名前のノードを追加します。※似た名前のノードが多いので注意

ⅳ.Amazon Echoノードの設定

パレット(左にあるノードが並んだ場所)の入力カテゴリに追加されたノード『Amazon Echo Hub』を、ワークスペースへD&Dしてダブルクリック。
ポートはファイアウォールに先ほど設定した”8111”を入力して【完了】を押します。

同じように『Amazon Echo Device』をワークスペースに追加して、上記のHubと接続します。
ここで設定するNameはAlexaから見えるデバイス名です。
名前は日本語が使えますし自由に決められますが、誤動作を防ぐために長くてユニークな名前を設定します。
動作確認以外では直接呼ぶ予定はないので、呼び易さは気にしなくてOK。

ⅴ.デバッグ用ノードを設定

パレットの共通カテゴリにある『debug』をワークスペースに追加して、Amazon Echo Deviceの出力と接続します。
debugノードの設定では、対象を『msgオブジェクト全体』に変更しておきましょう。
どんな値がどんな形で送られてくるのか未知数のため、ひとまず全部表示させます。

ここまでできたら、エディタ画面の右上にある【デプロイ】を押しておきます。

ⅵ.Alexaアプリに登録する

他のデバイスを登録する方法と同じ手順で追加します。
ただし、探すデバイスの種類は『その他』で探します。
問題なければⅳで設定した名前のデバイスが見つかり、照明として操作が可能になります。

ⅶ.呼びかけ動作確認

Echo Dotに話しかけてパソコンに指示が届くかを確認します。
右のサイドバーで虫ボタンを押してデバッグメッセージを表示できる状態にしてから、「アレクサ、〇〇〇を点けて」(〇〇〇は上で設定したデバイス名)と言ってみましょう。音声ではなく、スマホのAlexaアプリ上での操作でも可。
問題なければデバッグメッセージに何かが表示されます。何かが表示されればOK。

2.Node-REDの設定

Node-RED内で作ったデバイスは照明なので、コマンドとしては「点けて」、「明るくして」、「青色にして」、、、などが使えます。
でもやはり照明なので、「音量を上げて」や「画面を縦にして」ということはできません。
そのため、明るさや色で条件分岐を行って、定型アクションで使い分ける方法で対応します。

ここでは、明るさより明確に指示ができる”色”で実装します。
あとから知ったけど、「明るさを〇%にして」というコマンドを受け付けられるみたいなので、明るさの方が楽だと思います。

ⅰ.流量を制限する

試していたら1回の音声操作で、ほぼ同時に同じコマンドが2つ送られることが分かりました。
設定を間違えているのかバグなのかは横に置いておいて、とりあえず対策します。

機能ノード『delay』をワークスペースに追加して、『Amazon Echo Device』の出力を繋げます。

動作を”メッセージの流量制限”、”全てのメッセージ”
流量を”1メッセージ/1秒”、”中間メッセージを削除
これなら問題が知らない間に解決しても悪影響は出ないはず。。。

ⅱ.RGBをまとめて丸める

Alexaから送られてくる命令をデバッグで見ると”rgb: array[3] 0: 254 1: 254 2: 0”というかんじで配列です。Node-REDの条件分岐ノード『switch』では、ひとつの値しか扱えないようなので、1つの値にまとめます。
また、RGBは数値ではなく色名で指定する都合上、256×256×256を表現できません。恐らくアプリ内に表示された選択肢の15色までしか使えない。
各値の範囲は0~254までっぽくて+1するわけにもいかないので3桁に丸めます。

機能ノード『function』をワークスペースに追加して、『delay』の出力を繋げます。
ノードの設定では名前は任意、コードには以下をコピペ。

function rgb2hex(rgb){
return "#"+rgb.map(function(value){
return ("0"+value.toString(16)).slice(-2) ;
}).join("");
}
s = rgb2hex(msg.rgb);
msg.code = s.replace(/\w./g,x=>(('0x'+x)/17+.5|0).toString(16));
return msg;

配列(254,0,254)を6桁のカラーコード(#fe00fe)にして3桁(#f0f)に丸めています。()内は例。
#は先頭が0の値が消えないか不安だったので付けましたが恐らく不要です。

ⅲ.RGBで条件分岐させる

msg.codeに入っている値で条件分岐させます。
機能ノード『switch』をワークスペースに追加して、『function』の出力を繋げます。
ノードの設定では名前は任意、条件は使うだけ(最大15色たぶん)用意していきます。

プロパティには『function』ノードで出力した変換後の値”msg.code”を指定します。
条件は”==”、値は3桁RGBを#付きで指定します。

ⅳ.処理を実行させる

機能ノード『exec』をワークスペースに必要数追加して、『switch』の出力を繋げます。
『switch』の出力は設定した条件の数だけ用意され、上から順に該当しますし、出力端子(なんて言うんだ)のマウスオーバーで条件が表示されます。

コマンドの中身はプログラムの実行ファイルやスクリプトファイルを指定します。
名前にはRGBコードを書いておくとワークスペース上で分かりやすいです。

3.定型アクションの登録

定型アクションの作成は、照明として認識された仮想デバイスに対して色を指定します。
「アレクサ、ライトを青色にして」といったアクションを全く違う音声コマンドで登録します。

例えば、
実行条件:「アレクサ、パソコンの画面を縦にして」
アクション:仮想デバイスの電源:オン、明るさ:100%、色を指定:あかむらさき

その結果、Node-RED内で作成した仮想デバイスにRGBを”#f0f”にする指示が届きます。

注意点としては、全てのアクションで明るさを100%にすること。
明るさを変えると同じ色を指定してもRGB値が変わってしまい、明るさを指定しないと前回の明るさを保持するため、色指定だけでは意図したRGB値を送ってくれなくなります。

さいごに

色ですと15色までしか使えないけど、明るさなら0~100%まで101個のコマンドが組める!と思ったけど、仮想デバイスを増やせば色でも戦えることに気付いたけど、この方法だと音声コマンドの表現が登録したものに限られてしまうけど、そもそもそんなに音声でやらせたいことが少ないことに気付きました。

Node-REDは素人でも組みやすく、ノードさえあれば異なるサービスとサービスを繋ぐには便利そうです。
半面、細かい処理、特に複雑な条件分岐やループ処理等は不向きなようなので、これだけでシステムを完結させるということはなさそう。

とはいえ、ライトを暗くしてエアコンを消してパソコンをシャットダウンしてという作業が「おやすみ」の一言で完了させることができて満足です。