Tuesday, April 17, 2018

Commanding a Roomba with Alexa and Raspberry Pi (4): Controlling the TV from Node-RED

In the previous articles we connected Node-RED on Raspberry Pi to Alexa and copied TV remote IR codes.
This time we finally wire up the full chain: Alexa → Node-RED → IR → TV.
  1. Gather parts.
  2. Set up Node-RED on the main Raspberry Pi and register it with Amazon Echo Dot
  3. Headless WiFi setup for Raspberry Pi Zero W
  4. Copy IR remote codes with Raspberry Pi
  5. Call IR functions from Node-RED to control the TV [This article]
  6. Control Arduino via HTTP API using FlashAir GPIO mode
  7. (Bonus) Control Roomba from Arduino via ROI serial interface
  8. Control Roomba from Arduino via IR
  9. Control Roomba from Node-RED via FlashAir/Arduino

When calling IR functions from Node-RED, there are two scenarios:
  • IR LED attached to the same Raspberry Pi running Node-RED (hub)
  • IR LED attached to a separate Raspberry Pi from the hub
Let's start with the first case.

Calling lirc from Node-RED on the Same Pi

Integrating Node-RED and lirc on a single Raspberry Pi is very straightforward.
Open the node installation screen using the same steps as when setting up Node-RED.
Search for the keyword "lirc" and you'll find a node called "node-red-contrib-lirc" — install it.
After installing, "lirc" appears in the output node list like this:

Drag the "lirc" node and drop it into the canvas.
Double-click the dropped lirc node and configure it as shown:

"Name" can be anything — just use something descriptive.

"Controller" is the first argument to the lirc command on Linux.
To send once, use "SEND_ONCE".

"Device Name" is the device name you specified with irrecord.
Since we registered a device called "TV" last time, enter "TV".

"Output" is fixed at "1".
This appears to be reserved for when lirc supports multiple IR LEDs — currently only one is supported, so set it to "1".

Sharp eyes will notice something: device "TV" has multiple remote buttons, but there's no field to specify which one.
Buttons like "on" or "ch1" need to be specified somewhere.
In the lirc node, button names are passed via the message payload.

What is the Message Payload?


In Node-RED, messages are passed from one node to the next.
By default, messages are in JSON format and referenced as the "msg" object.
The elements inside msg depend on the upstream input, but every input carries at least one element called "payload".
Most nodes interpret msg.payload as their input parameter.

The lirc node interprets the value of msg.payload as the remote button name.
So when connecting a flow to the lirc node, setting msg.payload to "on" will send the "on" signal to the TV.
(Provided "on" is defined in TV.lircd.conf.)

With that in mind, let's wire up the input side of Node-RED.

Connecting to Alexa Input

Add "alexa local" from the "input" list in Node-RED.
Name it "テレビ" (television).
As mentioned before, this name becomes the device name Alexa will recognize — so be careful here.

Next, add a "template" node from the "function" list and draw a wire from the right side of the alexa local node to the left side of the template node.
Double-click the template node.
This template node is where you assign the msg.payload value to pass to lirc.

"Name" — give it something descriptive.
"Set" — the variable to assign to. In this case, "msg.payload".
Since we want a fixed string, set "Format" to "plain text".

Whatever you write in the template field gets assigned to msg.payload.
In this case, "on".
Writing something like "{{hoge}}" would embed the value of the incoming msg.hoge variable.
Setting "Syntax" to JavaScript lets you compute and assign a result dynamically.

Once configured, wire the right side (output) of the template node to the left side (input) of the lirc node.
Press the "Deploy" button in the top right to save the flow.

If Alexa hasn't discovered the "テレビ" device yet, say "Alexa, discover devices" and it should find it.


Testing with Alexa

Stick the Raspberry Pi's IR LED near the TV's IR receiver.
Now say "Alexa, テレビをつけて" — and the TV should turn on.

If it doesn't work, add a debug node to inspect the msg object and confirm the correct message is reaching the lirc node.
If the message is passing through correctly, check whether lirc is returning errors on the Linux side.
If that's also fine, try swapping the IR LED for a regular LED to check if it actually lights up.
Since hardware, software, and network are all involved, debugging means methodically isolating each contact point — unglamorous but necessary.


Running Node-RED and lirc on Separate Raspberry Pis

The idea is to send something over the network from Node-RED and have the lirc side receive it.
You could call a shell command from Apache on the lirc side, but it's also fine to just run another Node-RED instance there.
Overkill, but it works.

On the lirc-side Node-RED, add an "http" input node and specify a path.
Then call that path from the hub side.
Wire the http node to the lirc node — that's your lirc HTTP API done.

On the hub side, add an "http request" node from the "function" list.
Double-click it and configure the IP address of the lirc Pi and the path from the http input node — that's all it takes to call it.

Everything else is the same as running Node-RED and lirc on the same Pi.
That said, if you're running Node-RED on both sides anyway, it might be simpler to just add the alexa local node to the lirc-side Node-RED directly.

Done

And with that, Alexa and the TV are connected.
With some effort in Node-RED, you can go well beyond power on/off — like picking shows from a recording list and playing them back.

Next we'll wire in the Roomba as well.

No comments:

Post a Comment