You are on page 1of 9

CamJam!

Workshop: Node-RED and controlling Minecraft with JavaScript



An introduction to flow-based
programming using Node-RED
http://nodered.org


! Node-RED is a visual tool for wiring the Internet of Things (IoT). Node-RED is
platform-independent, but has been developed with small computers such as the
Raspberry Pi in mind.

! Traditional IoT development can be very technical: Access to the GPIO and other
hardware requires skills in C or assembler, output of data to web services or sending
tweets and emails requires the use of complex APIs. Node-RED takes care of the
technicalities and lets you concentrate on the logic of your workflow

! While most programming in Node-RED is done visually using pre-defined functions
(nodes), any additional functionality can be added in JavaScript.

! Node-RED is a multi-purpose survival tool use it for any prototyping!


WORKSHOP CONTENT: In this workshop, were going to use Node-RED as a development
tool for JavaScript. Building on functionality available for generic programming challenges,
were going to use the communication standard TCP (Transmission Control Protocol) to
interact with the Minecraft API (Application Programming Interface).

-1-
CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
Technical background: For this workshop, you will find a Raspberry Pi with Node-RED already installed. While the installation of Node-RED
software is relatively easy, it would be difficult to include this step within the time constraints of the exercise. On a fresh and up-to-date
Raspian installation we added: node.js, npm and Node-RED as per:

http://nodered.org/docs/hardware/raspberrypi.html

Note: On your own system, to leverage the power of Node-RED, consider installing the node for GPIO access as well.


1) Exercise: Starting Node-RED as Raspberry Pi user
Node-RED can be installed as a service on the Raspberry Pi, i.e. as a program thats always
executed when your Pi is running. However, this is only useful if you want to commit your Pi
for this particular use as it can consume considerable resources. For everyone else, its
recommended to start Node-RED only when needed:

1. Open the LXTerminal to see a console that allows you to enter Linux commands.
2. Start Node-RED by issuing node-red.

You should now see Node-RED starting up that may take a few seconds:


Congratulations. Youre now ready for the exercises.
Node-RED represents a server on the basis of node.js and interacts with the user through a
graphical user interface. It can be reached on port 1880. To use Node-RED, open a web
browser and direct it to http://localhost:1880
Its useful to remember that Node-RED acts as a server in your entire network. That is, if your Raspberry Pis internal IP address is something
like 192.x.x.x, every computer in your network can open the Node-RED GUI through http://192.x.x.x:1880. You can make your system more
restricted/secure by following the configuration advice on http://nodered.org/docs/security.html.

2) Exercise: Your first flow this is a recap for those who attended the last course(s)
The best way to explain a flow is by creating one. In this mini flow, were going to inject a
value into our debug window (refer to page 1 for what the GUI elements are called).

1. Open the Epiphany Web Browser. (It supports JavaScript better than Midori).

2. In the address line, enter localhost:1880. You will then see the Node-RED GUI.

-2-
CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
3. Drag and drop an inject node from the nodes library into the flow editor (once
youve chosen the inject node, you should see some general explanation about its
functionality in the info pane no need to read that now).
4. Drag and drop a debug node from the nodes library into the flow editor.
5. Create a pipe between the inject and debug nodes by drawing a connection between
their small grey rounded rectangles.
6. Change from the info pane to the debug pane (upper right).
7. Deploy (=start) your flow.

8. Once deployed, press the left blue rectangle thats attached to the inject node. Check
whats happening in the debug pane. (Yes, thats a Unix time stamp).


3) Exercise: Finding the Minecraft API and understanding the protocol
1. Open another LXTerminal and change to your Minecraft installation by issuing cd
/opt/minecraft-pi.
2. In the API directory (cd api), get a list of available files and directories (ls).
Those with previous programming experience may recognise the python sub-directory.
Inside you would find the files that expose the Minecraft functionality of the mcpi package
to Python. Its important to note that the Application Programmers Interface (API) be
it for a locally installed application like Minecraft or a web server that listens to your
commands over the Internet is just a convention on which interface (local socket or IP
address, port) an application is listening to other programs (like yours), which commands
are available and what parameters in which formats are expected.
The mcpi package encapsulates these concepts (connection, commands) in easy-to-use
Python commands. Sometimes the underlying specification is not communicated and as a
programmer youre stuck with the functions available in the higher-level library. However,
the Minecraft API is rather transparent and if you
3. Change into the spec directory (cd spec), you are going to find mcpi_protocol_spec.txt
a humble text file with the information that you require.
4. Open the file in an editor (nano mcpi_protocol_spec.txt) and have a look around.
Most modern web services (including Twitter or the BBC) provide APIs for programmatic retrieval of information. If youre interested how to
use APIs over the Internet in Node-RED, Ive put up a guide on accessing IoT platforms that can serve as an entry point:
http://www.slideshare.net/BorisAdryan/node-red-iotplatformtest

The specification states that the Minecraft binary listens to incoming messages at TCP port
4711 and expects character strings that are terminated with a \n (Unix linefeed). A
following schematic of the Open Systems Interconnection (OSI) Model helps to digest this:
In a nutshell, once a physical connection is established between two devices (Level 1) and
they can exchange signals (Levels 2+3), Level 4 in the OSI Model takes care of housekeeping
jobs: Is there an error in the communication? Can we recover from small errors? Do
-3-
CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
information packages arrive in the right order? While some protocols like UDP optimise for
high throughput (little error checking, little redundancy), others are slower but more secure
in terms of data integrity (like TCP).


http://programmerhelp404.blogspot.co.uk/2014/01/iso-osi-layer-model-tcpip-model.html

Its important to understand that these communication routes exist on the Internet, but at the
same time localhost (IP: 127.0.0.1) offers the same functionalities on your local computer. One
can imagine the communication via the Internet Protocol (IP, Level 3) like a motorway, but
there are 65536 (216) different lanes, commonly referred to as port.

4) Exercise: Hello World in Minecraft, Node-RED style


Please start Minecraft and open a new world. You may want to arrange the console
windows, the browser and Minecraft to your liking yes, theres always too little space on
that screen and Model 1 Raspberry Pis are not the fastest machines to do this.
In Node-RED,

1. Double-click your input node, and once the associated dialog opens, change the
Payload to type string and write Hello World in the empty text field below.

-4-
CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
2. Drag-and-drop in a function node. This is the node type that allows you to directly
interact with Node-RED messages (by default having a payload and a topic) in
JavaScript.
3. In your function node, write msg.payload = "chat.post("+msg.payload+")\n"; before
return msg;
This line is going to take the incoming msg.payload (Hello World), and assigns new
content chat.post(Hello World)\n to the variable. chat.post is a command weve
learned from the mcpi_protocol_spec.txt, and Minecraft is going to assert it as such
when its followed by a line break (Unix definition: \n).
4. Drag-and-drop a TCP node from the output panel. Set it up with the following
parameters:


5. Connect the nodes like this:


6. Deploy. Test your flow by triggering the inject node. Do you see what you expected?

5) Exercise: Move Steve around - and build stuff

Youve been there before, but probably in Python. Now try it with raw ASCII strings.
1. Have a look around the protocol specification and look for the command that sets the
player to a new coordinate.

2. Set a wooden block directly in front of you. (Hint: blockTypeID for wood is 17; and
hard-code the coordinate for now).

-5-
CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
6) Exercise: Retrieving values from Minecraft

So far our interaction with Minecraft was rather one-directional. We just sent command
strings that had an effect on the Minecraft world. Now were going to modify our flow so we
can query values like our own position via the API.
The overall anatomy of our flow is going to look like this:


1. Use an inject node (here named trigger) to start the flow.

2. In the appropriate function node, set msg.payload = "player.getPos()\n";


3. Instead of a TCP out node, were now going to use a TCP request node that allows for
bi-directional communication. Configure the node like this:


Just as we indicated the end of our message to the server with a \n character,
Minecraft terminates its return messages with the same character.
4. By default the TCP request node returns a buffer, and we need to convert the
information from Node-RED using msg.payload = msg.payload.toString(); in a
function node.
5. The flow concludes with a debug node. If youre having trouble with the flow, consider
sending output to debug panel and console.

6. Deploy. Have a walk around Minecraft and trigger your flow. Do you see what you
expected?


7) Exercise: Event-driven programming and loops
By now you may have realised that our Node-RED flows were linear series of commands. Once
triggered, we sent a command, retrieved information and displayed it. But, for example, how
can we iterate over a set of coordinates and execute world.getBlock(x,y,z) for Steves
immediate neighbourhood?

-6-
CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
For this, were going to extend our flow a little bit. First, look at the overall anatomy of our
flow. Its a bit of a mouth full:


First, we translate Steves position into a series of (x/y/z) coordinates, more specifically, a
cube that this directly underneath Steves feet. Then, were going to query each block in the
Minecraft world for its content. Next, we tabulate the elements weve found and provide a
summary in the debug panel. The tutorial is going to guide you through the necessary changes
bit by bit.

1. Change the .toString() function node. Ive renamed it to position to () string to better
reflect its new functionality:

-7-
CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
Optional reading: The .trim function removes the invisible trailing \n from the
players position, and with .split(,) we separate out the x, y and z component of the
coordinate into an array called pos. Due to the way Minecraft considers player
positions as floating point numbers, but places elements in discrete blocks, we need to
round our position with the Math.round function. JavaScript can occasionally act a bit
funny, so to about any problems, we specifically tell it to interpret the character strings
in the pos array as floating point numbers with parseFloat. Ultimately, we are going to
define an array called coordinates, and each element inside coordinates is a payload
with a string in parenthesis, featuring a coordinate of the cube below Steve.

Obligatory reading: By returning [coordinates] at the end of the function (line 30, note
the [ ]), were going to tell Node-RED to trigger the next node for reach element in the
array.
2. Add a function node and add msg.payload =
"world.getBlock"+msg.payload+"\n"; - this simply makes the
overall code more readable. It complements each (x,y,z)
triplet with the world.getBlock command, followed by \n;
3. Add another TCP request node and configure it exactly like
the one before.
4. The material .toString() function node adds exactly this
functionality: msg.payload = msg.payload.toString(); add a
debug node if you want to check your results. A table with
common elements is shown in the figure, from
http://minecraft.gamepedia.com/Data_values_(Pocket_Edition)
5. The function node tabulation counts how many times each
element of the Minecraft world was seen in the 5x5x5 = 125
blocks underneath Steves feet. Because tabulation is invoked
every time a new element is detected, we need to make use of
a Node-RED trick: The context variable remembers its state
between iterations.


-8-
CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
To prevent summing up of elements of different trigger events, we modify the inject
node with a topic called trigger. If the tabulation node is invoked from the inject
button (note the new connection!), we delete the variable by assigning it the value
undefined. However, if we invoke the function from the material .toString() node, we
make sure we interpret the code as String. If our table is still undefined, we create it as
array, otherwise we use the existing one (line 8). If the ID has been seen before, we
take its current count, otherwise we assign 0 (line 9). Then we increase the count for
this observation (this event only) of seeing the ID (line 10). Ultimately, we return our
table as message.

6. To prevent the printing of our table while it is still being generated (remember, the
tabulation method gets invoked 125 times!), we make use of the trigger node.
Configure it with the following settings:


The node remembers the first time it was triggered, and only if it hasnt received any
new messages for 250 milliseconds, passes the information on to the final debug node.
7. Deploy and take Steve for a walk. Trigger the inject node. Wait patiently. Check the
console and/or debug panel for output. Does the output make sense to you?

Conclusions
Node-RED is an incredibly powerful framework that allows you to do things in very little time.
The official directory of flows donated to the community is here http://flows.nodered.org
and they can easily be imported by copying & pasting the JSON-formatted code.

Given the availability of a convenient input node, try to display tweets with a particular
hashtag in Minecraft. Youre going to be surprised how simple it is!

Theres a bunch of other Node-RED tutorials at http://www.slideshare.net/BorisAdryan and


occasional Node-RED tips at @BorisAdryan.

-9-

You might also like