Lab 3: SPOT Radio Communication
Background Reading:
SunSPOT
Developer's Guide, pages 25-37:
Before starting this lab, you should look over these pages of the SPOT
developer's guide which briefly cover the provided SPOT device libraries. Some of this can be skimmed; the idea is for
you to get a feel for the SPOT API that you will be using to develop
applications, and hopefully pick up ways to do some of the most common
tasks. Do pay close attention to the
section on the radio communication library, starting on page 29, though, as
that is what this lab is concerned with.
Socket Programming Introduction: http://www.javaworld.com/javaworld/jw-12-1996/jw-12-sockets.html. If you haven't
encountered Java socket programming before, it would be a good idea to go
through this tutorial that introduces the concepts and relevant parts of the
Java API. The JavaWorld
tutorial, though good, only covers TCP sockets.
For a brief coverage of UDP socket programming in Java, check out these
slides: http://www.cs.rpi.edu/courses/fall02/netprog/notes/javaudp/javaudp.pdf.
Prelab Question: What is the difference
between the Radiogram and the Radiostream protocols
provided by Sun for SPOT applications?
Which standard networking protocol do each of
these resemble?
Introduction:
Now that you are familiar with the SPOTs
and know how to put applications on them and start a shared basestation,
it is time to start developing applications of our own. For this exercise, we are concentrating on
learning about radio communication, which is how SPOTs talk to each other (and
the basestation), and an essential part of almost
every sensor network application. .
For this lab, we are going to
develop an application to be run on two SPOTs where each SPOT sends out a
number and the other SPOT uses its LED's to display the number it
receives. Each SPOT will constantly be
counting up, so you should see the displayed number (i.e. The color and LED's
that you see illuminated)
changing. We will not be
starting from scratch; instead, we will start with the RadioStrength
demo provided by Sun. When the RadioStrength demo is placed on two SPOTs, the LED's on
each SPOT indicate the strength of the signal that that SPOT is receiving.
1.
Start new project. Since we are
starting from the RadioStrength demo, we will just
copy that project and then modify the source file. Open the RadioStrength project, which is found in (no
surprise) the Demos folder. Right click on the project and select “copy project.” I recommend naming the new project RadioCount, but you are welcome to choose another name if
you so desire.
2.
Examine the code. Open up the source file for the RadioStrength project in Netbeans,
RadioStrength.java. Each node has two
primary tasks: it sends out a signal, and receives signals from over the air, then using the LED's to display the strength of the
received signal. In the program we are
creating, each SPOT performs two similar tasks: it counts up then sends out the
current number, and receives
a number and then displays it (the one received, not its
own). Knowing this, identify the methods
that RadioStrength uses for each of its two main
tasks, and postulate which will be used for which task in RadioCount
(Question 3.1).
Question 3.1: What are the names of the methods
that will continuously perform the send and receive tasks in RadioStrength, and which do you think will be rewritten to
count/send, and which to receive/display the number?
3.
Replace the transmit loop. In the method that
represents the transmit loop (should be obvious…) we will count up and then
send the number over the radio. The
communication is achieved through the use of the Radiogram protocol, which
should seem clearly similar to UDP sockets in Java
with Datagrams.
First a connection is opened with Connector.open() and assigned to a DatagramConnection
object. Then the Datagram to be sent is
constructed (in this case to contain the number that we have counted to so
far), and the send() method is invoked on our DatagramConnection instance to send the Datagram over the
radio to be picked up by another SPOT.
This is the code that should replace the main “while(xmitDo)”
loop in the transmit method for our RadioCount
program:
while (xmitDo)
{
try {
txConn = (DatagramConnection)Connector.open("radiogram://broadcast:" +
BROADCAST_PORT);
Datagram xdg
= txConn.newDatagram(txConn.getMaximumLength());
while
(xmitDo) {
for(int i=0; i
< 12; i++) {
for
(int count=0; count < 256; count++) {
xdg.reset();
xdg.writeInt(count);
xdg.writeInt(i);
txConn.send(xdg);
pause(1000);
// some pause is needed, otherwise LED's won't be able to keep up
}
}
}
} catch (IOException
ex) {
} finally {
if (txConn != null) {
try
{
txConn.close();
} catch (IOException ex) { }
}
}
}
4.
Replace the receive loop. Now it’s time to
replace the RadioStrength receive loop with one of
our own. The opening and instantiating of the connection and the creation of a
Radiogram object are similar to the transmit loop. You will notice, however, that now our
connection is declared specifically a RadiogramConnection
instead of just a DatagramConnection and that we are
dealing with Radiograms in particular and not just any old Datagrams. Instead of sending, here we receive a
Radiogram from our connection and then read the number from it (notice how
closely using Radiogram connections resembles dealing with other Stream types
in Java, which include sockets) that we then send on to the DisplayNumber() method to be
displayed on the LED’s. Here is the code
for the receive loop:
while (recvDo) {
try {
rcvConn = (RadiogramConnection)Connector.open("radiogram://:" + BROADCAST_PORT);
Radiogram rdg
= (Radiogram)rcvConn.newDatagram(rcvConn.getMaximumLength());
statusLED.setColor(getGreen());
pause(1000);
statusLED.setOff();
while
(recvDo) {
rdg.reset();
rcvConn.receive(rdg);
int num = rdg.readInt();
int index = rdg.readInt();
displayNumber(num, colorList[index]);
}
} catch (IOException
ex) {
} finally {
if (rcvConn != null) {
try
{
rcvConn.close();
} catch (IOException ex) {}
}
}
}
5.
Add the colorList
field. You will notice in the code above that when
we call displayNumber(), we refer to a variable named “colorList.” The idea is for colorList
to be an array containing the twelve predefined colors provided by Sun so that
the second value we extract from each Radiogram is an index that refers to one
of these colors. LED colors are of the
type LEDColor, and can get created to be any
combination of RGB (red, green, blue) values.
The predefined colors are all of the form LEDColor.COLORNAME. You will notice that in the original RadioStrength code, there are some colors manually defined
(in this example, RGB values are entered at time of object construction,
however they can also be changed and accessed later). In the future, you may well want to define
your own colors, work with in between values, or gradually change hue. The order that the colors are listed in the
declaration/initialization of colorList will
determine which color is associated with which index value; consequently,
changing the order of the colors in the line below will change the order in
which the colors are cycled through in the “counting up” process (and which is
displayed first). We want “colorList” to be a class
field, so place this code inside the class, but
outside of any method:
private LEDColor[] colorList = new LEDColor[] { LEDColor.ORANGE, LEDColor.WHITE,
LEDColor.PUCE, LEDColor.YELLOW,
LEDColor.MAUVE, LEDColor.MAGENTA,
LEDColor.CHARTREUSE,
LEDColor.BLUE,
LEDColor.CYAN, LEDColor.GREEN,
LEDColor.TURQUOISE,
LEDColor.RED };
6.
Build and deploy RadioCount. Once you’ve changed the code, go ahead and build the project, deploy onto your two SPOTs, and watch the
Radio Count program in action.
When you first reset your SPOTs after loading the application, you will
briefly see a red light that will then turn green and finally turn off; at that
point displaying of numbers should begin, assuming there is at least one other
SPOT to receive from. You've just
successfully created and deployed your first Sun SPOT application of your own
(though you were given the code)! NOTE: If this project is being done in
proximity to others doing it as well, you should be aware that your SPOT will
display any numbers it recieves as soon as a new
Radiogram is received. With just two
SPOTs, each should show only a sequential advancement; when others are sending
in the area as well, the different values being received will all be displayed,
but sometimes only extremely briefly (as soon as a new Radiogram comes in, that
contents will be immediately displayed).
Often in the latter scenario, each SPOT will still pause momentarily on
each number from one source, but each time it changes to the next value, other
numbers may be rapidly flashed before the next value of the primary sequence is
displayed. Changing the behavior of your
SPOTs to only display numbers received from a single source is posed as a
challenge below.
Challenges:
1.
Now
that you've got RadioCount running with two motes
counting for each other, what can you do to personalize the behavior of your
SPOTs? If other groups near you are at
this stage as well, how can you tell from whom each SPOT is receiving each
number that they are displaying? Try to
come up with a way to be sure that what your SPOTs display only comes from
another of your SPOTs. You could, for example, include something to identify
SPOTs running your application in each Radiogram sent out and then only display
a number if the Radiogram that is received contains that identifier as well as
the counted number and color index.
Another idea is to have your SPOTs send numbers that conform to a
different pattern (count up in increments of two, for example, and then when
reaching the maximum go back down hitting all the missed values. There are many possibilities for using this
approach), keep track of the last value displayed, and then only display new
values that fit the pattern.
2.
Currently,
the counting works by going through all 256 possibilities for the eight LEDs
with a single color (each LED being either on or off) and then repeats the
process with a new color. Change your
application so that the counting (on the sender side) first cycles through all
twelve colors for each unique LED combination (values 0-255 of the “count”
variable in the transmit loop) before advancing to the next one. So, this means the value “1” is displayed in
all twelve colors before “2” is displayed at all.
Question 3.2: With twelve colors like we are using (one
could theoretically define as many as they wish), this allows for 12 x 256 =
3072 display possibilities. How would
you go about changing the application that so that 13^8 possibilities could be
displayed? In other words, each of the 8 LED's could be either off or
illuminated one of the twelve predefined colors (this case differs from before
by allowing different LED's to display different colors at the same time).
Conclusion: The goal of this exercise and the RadioCount application was for you to gain confidence about writing your own programs with the help of the demos and code pieces provided with the SPOT SDK and to introduce you to using the SPOT radio communication library. When the time comes to create your own applications from scratch, you will be able to look back on this exercise to remember how to handle communication between motes. Hopefully it will serve as a stepping stone to bigger and better things.