2018年4月17日火曜日

Alexa と Raspberry Piでルンバに掃除してもらう:(4)Node-REDからテレビを操作

前回まででNode-REDでRaspberry PiとAlexaを連携させ、さらに赤外線リモコンのコードをコピーしました。
今回はついに、Alexa → Node-RED → 赤外線 → テレビ という流れを全部繋ぎます。
  1. 材料を揃える。
  2. 母艦のRaspberry PiにNode-REDをセットアップしてAmazon Echo Dotに認識させる
  3. Raspberry Pi Zero WをヘッドレスでWiFi対応セットアップする
  4. Raspberry Piで赤外線リモコンのコードをコピーする
  5. Node-REDから赤外線機能を呼び出してテレビを操作する【今回】
  6. FlashAirのGPIO機能でArduinoをHTTP API経由で制御する
  7. (おまけ)ArduinoからROI経由でルンバを動かす
  8. Arduinoから赤外線経由でルンバを動かす
  9. Node-REDからFlashAir/Arduino経由でルンバを動かす

Node-REDから赤外線機能を呼ぶ場合、次の二種類のケースがあると思います。
  • 母艦のRaspberry Piに赤外線LEDを付ける場合
  • 母艦とは別のRaspberry Piに赤外線LEDを付ける場合
まずは前者から。

母艦のNode-RED から母艦の lirc を呼ぶ

1台のRaspberry Piの上でNode-RED と lirc を連携させるのは非常に簡単です。
Node-REDをセットアップした時と同じ手順でノードの追加画面を開きます。
「lirc」というキーワードでノードを検索すると「node-red-contrib-lirc」というノードが見つかるので追加します。
すると、こんな感じで出力のリストに「lirc」が増えます。

この「lirc」をドラッグして右の広いところにドロップ。
ドロップした「lirc」ノードをダブルクリックして図のように入力します。

「Name」は何でも良いです。分かりやすい名前をつけます。

「Controller」はLinuxのlircコマンドの第一引数です。
今回は1回送信したいので「SEND_ONCE」です。

「Device Name」はirrecordコマンドで指定したデバイス名です。
前回「TV」というデバイスを登録したので「TV」。

「Output」は「1」固定です。
lirc が複数の赤外線LEDをサポートした時のために用意されているようですが、現状では1個しか使えないので「1」。

ここで勘の良い方は「あれ?」と思うかもしれません。
デバイス「TV」には複数のリモコンボタンがあるはずなのですがその設定がありません。
例えば「on」とか「ch1」とかをどこかで指定する必要があるはずです。
lircノードではメッセージペイロードでこれらのボタン名を指定します。

メッセージペイロードとは


Node-RED では前のノードから後のノードに対してメッセージが渡されます。
デフォルトではメッセージはJSON形式で書かれるようです。
このメッセージには「msg」というオブジェクト名がつけられています。
msgオブジェクト内の要素は上流の入力次第なのですが、どの入力も「payload」という要素を1つ持っています。
多くのノードで、この msg.payload を入力パラメータとして解釈する仕様になっています。

lirc ノードでは msg.payload の値をリモコンのボタン名として解釈します。
つまり、lirc ノードにフローを繋ぐ際、msg.payload に「on」を代入すればテレビに対してonの信号が飛びます。
(TV.lircd.conf に「on」が定義されていれば、ですが。)

この約束を頭の片隅に入れておいて、Node-RED の入力側からフローを繋いでいきます。

Alexa からの入力とつなぐ

Node-REDの「入力」のリストから「alexa local」を追加します。
名前は「テレビ」。
前にも説明しましたが、この名前がAlexaで呼びかける時のデバイス名になるので要注意です。

さらに、「機能」のリストから「template」を追加して、alexa local の右側からtemplate の左側に線を繋ぎます。
繋いだらtemplateノードをダブルクリック。
このtemplateノードで、lirc に渡す msg.payload を代入します。

「名前」は適当に分かりやすい名前を付けます。
「設定先」は代入したい変数。今回は「msg.payload」ですね。
今回は固定文字列を埋め込みたいので「形式」は「平文」で構いません。

テンプレートのところに書いた内容が msg.payload に代入されます。
今回は「on」です。
「{{hoge}}」などと書くと、入力に渡された msg.hoge 変数の値が埋め込まれます。
「構文」を指定するとJavaScriptで演算した結果を代入することもできます。

設定できたら、templateノードの右側(出力側)をlircノードの左側(入力側)に繋いで完成。
右上の「デプロイ」ボタンを押すと保存されます。

もし、Alexa に「テレビ」デバイスを認識させていなければ「Alexa デバイスを探して」と言うと見つけてくれます。


Alexa から実行

Raspberry Piの赤外線LEDをテレビの赤外線受光部の近くに貼り付けておきます。
この状態で「Alexa テレビをつけて」と言うとテレビがつく、、、はずです。

うまくいかない場合は、debug ノードを追加して msg オブジェクトの中身を確認していき、lirc に正しくメッセージが渡っていることを確認します。
メッセージが渡っているようであれば、今度は Linux 上で lirc がエラーになっていないかを確認するとか。
それでも問題ないようなら、赤外線LEDを普通のLEDに付け替えてみて、ちゃんと光るかどうかを確認。
ハード/ソフト/ネットワークが絡み合っているので、1つずつ接点を潰しながら不具合箇所を特定する地味な作業になります。


別々のRaspberry PiでNode-REDとlircを動かす場合

Node-RED から何らかの方法でネットワークに飛ばし、lirc側も何らかの方法でリクエストを受け取れば良いです。
lirc 側で Apache からShellコマンドを読んでも良いのですが、いっそのこともう1つNode-REDを立ち上げても良いです。
オーバースペックですが。

lirc 側の Node-RED では「入力」の「http」ノードを追加して、好きなパス名を指定。
ここで指定したパスを、母艦側から呼び出します。
http ノードと lirc ノードを接続すれば、lirc 用 HTTP API の完成。

母艦側では「機能」の「http request」ノードを追加。
ダブルクリックして、lirc 側の IP アドレスと、「http」ノードのパスを設定すれば呼び出せます。

その他は同じRaspberry Piで Node-REDとlircの両方を動かす場合と同じです。
まぁ、Node-REDを両方に立ち上げるなら、lirc 側のNode-REDにalexa localノードを作った方が手っ取り早いですが。。。

完成

そんなこんなで、Alexa とテレビの連携が完成しました。
頑張ってNode-REDを設定すると、テレビのON/OFFの他に録画リストから番組を選んで再生したり色々できます。

次回からはさらにルンバと連携させていきます。

0 件のコメント:

コメントを投稿