MPEMessagingPart2
Search:
BigScreens / MPEMessagingPart2

This page is dedicated to just a few tricks to help you along with passing messages along.

Concatenating a long String

There are limits, of course, but let's consider the following situation. You want to read the pitch values from a microphone, coming in via SONIA as an array of floats. So first, you'll have to initialize all the Sonia stuff:

if (client.getID() == 0) {
  Sonia.start(this);
  LiveInput.start(256);
}

Then, you can ask for the values as an array of floats:

// One client gets the pitch values and broadcasts them
if (client.getClientID() == 0) {
  float[] spec = LiveInput.getSpectrum();

Now, we need to turn that array into one long String. We do so by using the "+" operator (concatenation for Strings) in a loop. In between each number, we will insert a comma -- this will help us later when it's time to parse out the content. While we're at it, we also might as well convert the numbers to integers and save some space. In other words, we have an array of floating points:

{100.32,5.23,6.92,15.32}

which we want to convert into a comma delimited String of integers:

"100,5,6,15"

Once we've got the String, we can broadcast it:

  String message = "";
  for (int i = 0; i < spec.length; i++) {
    message += (int) spec[i] + ",";
  }
  client.broadcast(message);
}

Incidentally, it's often better to use a StringBuffer when concatenating Strings, but in this case, it's not that much data and we'll be fine. Also, whatever you do, do not use a colon (":") in your String! MPE uses colons internally as a delimiter and if you use one, you're just asking for trouble.

Now, when you receive the data, you want to do the opposite, take the String:

"100,5,6,15"

and convert it back into an array of numbers.

{100,5,6,15}

As we know, this happens in frameEvent():

public void frameEvent(TCPClient c){

First we get the message itself:

  if (c.messageAvailable()) {
    String[] msg = c.getDataMessage();

We can safely assume that we only have one message and just look at the first (index #0) String in the array. We take that single String and split it up into an array of Strings using the split() function. The delimiter is, of course, a comma (",") since that's what we used when we first generated the message.

    String[] vals = msg[0].split(",");

Once we've got the array of Strings, we can make an array of ints that is the same size and convert each String one at a time:

    spectrum = new int[vals.length];
    for (int i = 0; i < spectrum.length; i++) {
      spectrum[i] = Integer.parseInt(vals[i]);
    }
  }

Multiple messages with ID numbers

There comes a time when broadcasting messages from one client is not enough. Let's consider that we have multiple cameras hooked up to multiple computers. In this case, we have 3 clients (IDs: 0,1,2) and cameras connected to clients 0 and 2.

// Only if I am client 0 or 2
if (client.getID() == 0 || client.getID() == 2) {
  // Using the default capture device 
  video = new Capture(this, 160, 120, 30); 
}

Now, when it comes time to broadcast the data acquired by the camera (in this case a single number, motion, but it could be many values) we want to be able to identify which camera it came from. We can use any protocol we want, for example, we could broadcast the message as:

ID COMMA MOTION

client.broadcast(ID + "," + (int) avgMotion);

If it was an array of values, we might do something like:

ID SEMICOLON VALUE COMMA VALUE COMMA VALUE, etc.

(Just remember, don't use a colon!!!)

On the receiving end, we now might have more than one message (from multiple clients) so we need to loop through them all! For each message, we will split based on the comma, with the first value being the ID and the second the motion.

    // Get the messages in an array
    String[] msg = c.getDataMessage();
    // We might have more than one message, loop through each one!
    for (int i = 0; i < msg.length; i++) {
      // Our protocol is ID COMMA VALUE
      String[] stuff = msg[i].split(",");
      // Get the ID (index 0)
      int id = Integer.parseInt(stuff[0]);
      // Get the value (index 1)
      float motion = Float.parseFloat(stuff[1]);
    }

Now, the above code isn't doing anything with the values, but check:

/home/dts204/bigscreens/examples2009/MPEMessagingExamples

and look at the "twocameras" package for an example that reads motion values from multiple cameras.

Messaging with the Asynchronous client

Another way you might want to do messaging is to send external data from a machine that is not part of actually rendering the displays, such as your laptop. You can do this with MPE's "asynchronous client." First you want to make sure you enable this when running the server.


java -jar mpeServer.jar -listener -screens3

Then you make a completely new Processing sketch (or command line java app) that has an AsyncClient object:


AsyncClient client;

Initialize it with the server and port 9003 (you can change the port if you want.)

// For testing locally
client = new AsyncClient("localhost",9003);
// At IAC:
client = new AsyncClient("192.168.130.240",9003);

Then, whenever you want, send a message. It could be information from a sensor, a microphone or just some protocol you make up! The code looks like this:

public void mousePressed() {
  client.broadcast("Your message here!");
}
Search
  Page last modified on October 24, 2009, at 09:38 PM