Node-Red is graphical programming interface that allows logic to be created using nodes that are wired together. Node-Red has been pre-installed in the Raspian OS since 2015 and it has a very easy learning curve.
In this blog I wanted to show an example of Node-Red being used with a five button LCD faceplate to play Internet radio stations.
For this project I used a basic USB powered speaker, a Rasp Pi and a Pi 5-button LCD faceplate. The cost of the faceplates start at about $10.
Getting Started with Internet Radio
There are a good number of Internet radio resources, https://www.internet-radio.com has a good selection of stations to choose from.
To find a URL of a radio station, look through the stations until you find what you like and then right click on the .pls link, and “Save Link as…”. Save this link as a file and then open the file in a text editor to get the URL.
MPD – Music Player Daemon
MPD is a Linux based music service that supports the playing of both music files and internet based radio stations. For command line operations that is also a MPD client application called mpc. To install both the service and client:
sudo apt-get install mpd mpc
Before I started building the node-red application I played with the mpc commands to ensure that I understood the basics.
Internet radio stations are added like a song list:
mpc add 'http://uk2.internet-radio.com:8062' mpc add 'http://live.leanstream.co/CKNXFM' mpc add 'http://66.85.88.2:7136'
Some key mpc control commands are:
mpc play # play the current station mpc play 3 # play radio station 3 mpc pause # pause the music mpc next # play the next radio station mpc prev # play the previous radio station mpc volume 90 # set the volume to 90% mpc volume +5 # increase the volume 5% mpc volume -5 # decrease the volume 5%
The mpc status command will show the volume, what is playing along with the current station number and total number of stations:
$ mpc status Comedy104 - A Star104.net Station: Doug Stanhope - To Tell You the Truth [playing] #2/4 1:45/0:00 (0%) volume: 75% repeat: off random: off single: off consume: off
Node-Red Logic
Node-Red can be started from the Raspberry Pi menus, or from the command line:
node-red-start &
To access the Node-Red web page, enter the Raspberry Pi ip address with port 1880, for example : http://192.168.0.121:1880
For this project two extra Node-Red components are needed, and they are for the LCD faceplate and the MPD music player. To add components use the “Palette Manager” option.
For the LCD faceplate, search for Adafruit, and select the i2c-lcd-adafruit-sainsmart component.
Similarly search for mpd and add the node-red-contrib-mpd component.
To create logic select a node from the left node panel and drag it onto the center flow palette, and then “wire” the nodes together.
For the Internet music example I used four function nodes, and the two i2cLED and the two MPD nodes. (Comment nodes are only used to explain the logic).
The first step is to double click on the MPD nodes and add an MPD server.
Select Button Logic
I used the select button to turn on and off the music player.
A context variable is created to save the current state of the player. Note: a context variable is only accessible for the node where it is defined..
The ic2_LCD_Input node message has a msg.button_name and msg.button_state item that is used to determine which button is pushed.
For the select button logic a group of messages was used to add the different radio stations.
// create an "is setup" variable var issetup = context.get('issetup')||0; if ((msg.button_name == "SELECT") && (msg.button_state == "pressed" )){ // if the setup hasn't been run, add a radio station playlist if (issetup === 0) { context.set('issetup',1); var msg0 = { payload:"clear"}; var msg1 = { payload:"add http://185.33.21.112:11029" }; // 1.FM Trance var msg2 = { payload:"add http://66.85.88.2:7136" }; // Comedy 104 var msg3 = { payload:"add http://live.leanstream.co/CKNXFM"}; // The One - Wingham var msg4 = { payload:"add http://185.33.21.112:11269" }; // Baroque var msg5 = { payload:"play" }; return [ [ msg0, msg1, msg2, msg3, msg4, msg5] ]; } else { context.set('issetup',0); msg0 = { payload:"pause"}; return msg0; } }
Up/Down Button Logic
The UP button will issue an MPD command equivalent to :
mpc volume +5
This will up the volume by 5%. The total volume will max at 100%.
The DOWN button will issue an MPD command equivalent to :
mpc volume -5
// Raise/Lower the volume var msg1; var thevolume = 5; //volume % increment to change if ((msg.button_name == "UP") && (msg.button_state == "pressed" )){ // if the setup hasn't been run, add a radio station playlist msg1 = { payload:"volume +" + thevolume }; return msg1; } if ((msg.button_name == "DOWN") && (msg.button_state == "pressed" )){ // if the setup hasn't been run, add a radio station playlist msg1 = { payload:"volume -" + thevolume}; return msg1; }
Current and Max Radio Station Logic
The ‘Current and Max Radio Stations’ node is updated from the MPD in node when there are any changes to the volume or when a new song or station is played.
This logic creates two flow variables (stnmax, stncnt) that are available in any node in this flow. The station max (stnmax) and current radio station (stncnt) variables are used in the LEFT/RIGHT button logic to determine which station to change to.
// Get the max number of radio stations and the current radio statio // Make context variables that can be used in other node, like the LEFT/RIGHT button var msg1 = msg.payload.status ; //create a simplier message var stnmax = msg1.playlistlength; flow.set('stnmax',stnmax); var stncur = msg1.nextsong; if (isNaN(stncur)) {stncur = stnmax;} // ensure a valid station flow.set('stncur',stncur); return msg1; // only needed for possible debugging
While the code is running it is possible to view the context date.
UP/DOWN Button Logic
The UP / DOWN logic changes between the radio stations using the mpc commands:
mpc next mpc prev
It is important to not move past the range of the radio stations or MPD will hang. The stnmax and stncur variables are used to determine if the next or previous commands are to be allowed.
// Move left and right in radion stations var stnmax = flow.get('stnmax'); var stncur = flow.get('stncur'); if ((msg.button_name == "LEFT") && (msg.button_state == "pressed" )){ // if the setup hasn't been run, add a radio station playlist if (stncur > 1) { var msg0 = {payload:"previous"}; return msg0; } } if ((msg.button_name == "RIGHT") && (msg.button_state == "pressed" )){ // if the setup hasn't been run, add a radio station playlist if (stncur < stnmax) var msg1 = {payload:"next"}; return msg1; }
Final Comments
The Pi LCD faceplate is an excellent hardware add-on for any Raspberry Pi project. However it important to know that clone hardware may work as expected. For my hardware I was not able to easily turn off the extra LED.
A future enhancement would be to add a Web interface so that you could change the volume or stations without using the 5 button Pi faceplate.