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. .

Radio Count: An Example of Using Radio Communication to Exchange Data Between SPOTs.

     

                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.