Go Down

Topic: How to get variable length data from Xbee packet (Read 1 time) previous topic - next topic

aetjansen

Mar 11, 2011, 11:06 am Last Edit: Mar 11, 2011, 11:47 am by aetjansen Reason: 1
Hi All,

I searched the (read only) forums, but did not find an answer, I hope someone can point me in the right direction.

For a project I have setup 2 Xbee modules in API mode, each on a different Arduino board. One sends sensor data to the other, which works fine. I am using the Xbee-Api library (found here: http://code.google.com/p/xbee-arduino/) from user Rappa (http://rapplogic.blogspot.com/)

However, I have trouble extracting the data (sensor values) from the received packet on the receiving Xbee. I only have a ugly method to get the data out, which is this (lines marked with -->):

Code: [Select]
    xbee.readPacket();
   
   if (xbee.getResponse().isAvailable()) {
     // got something
     //Serial.println("[Xbee] Received something on Xbee link");
     if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) {
       // got a zb rx packet
       //Serial.println("[Xbee] Got a zb rx packet");
       // now fill our zb rx class
       xbee.getResponse().getZBRxResponse(rx);
           
       if (rx.getOption() == ZB_PACKET_ACKNOWLEDGED) {
           // the sender got an ACK
           flashLed(RFLink, 3, 500);
       } else {
           // we got it (obviously) but sender didn't get an ACK
           flashLed(ERRLED, 2, 20);
       }

       uint8_t* rxData = rx.getData();

-->        Serial.println("Received: [" + packetMessage + "]");
-->        Serial.println("<START DATA>");
-->        String dataString = "";
-->        for (int i = 0; i < 35; i++) {

-->          dataString +=  rx.getData(i);
-->          Serial.print(rx.getData(i), BYTE);
-->        }

-->        Serial.println("<END DATA>");
       .
       .
       .
       


That does get me a string of 35 characters, however this seems to be the maximum I can send succesfully, but the messages are not always that long.

So, I tried this:
Code: [Select]

    xbee.readPacket();
   
   if (xbee.getResponse().isAvailable()) {
     // got something
     //Serial.println("[Xbee] Received something on Xbee link");
     if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) {
       // got a zb rx packet
       //Serial.println("[Xbee] Got a zb rx packet");
       // now fill our zb rx class
       xbee.getResponse().getZBRxResponse(rx);
           
       if (rx.getOption() == ZB_PACKET_ACKNOWLEDGED) {
           // the sender got an ACK
           flashLed(RFLink, 3, 500);
       } else {
           // we got it (obviously) but sender didn't get an ACK
           flashLed(ERRLED, 2, 20);
       }

       uint8_t* rxData = rx.getData();
-->        String packetMessage = dataToString(rx.getData(), rx.getDataOffset() + 1, rx.getDataLength() - 1);
       .
       .
       .
       

and added the dataToString function to the sketch:
Code: [Select]

String dataToString(uint8_t* msg, int offset, int length) {

 uint8_t i;
 String dataAsString = "";
 
 for (i = offset; i<offset + length; i++) {
   dataAsString +=  (byte)msg[i];
 }
}


It all compiles and runs, but leaves me with an empty string returned. When I Serial.print the two integers (rx.getDataOffset() + 1 and rx.getDataLength() - 1), the values are null. Nothing is shown, explicitly casting the values to (int) did not work either.

I took example code from the Droplet project from Rappa's website (here: http://rapplogic.blogspot.com/2009/08/droplet.html).

I must be missing something here, and I guess I am messing with the pointer or something, but I can't figure out what's wrong?

Does anybody see what I am missing maybe?

PaulS

When you declare a function that returns a value, you need to include a return statement to actually return a value.

Why are you adding one to the offset defined in the packet when calling your function to extract the data?

rxData is defined as a pointer to the data. Why do you need to create another function to make a copy of the data? Why can't you just access the data directly?

aetjansen

Hi PaulS,

Thanks for the reply. The reason for using that function was because I found it in example code from the original author and was trying to see how that would work.

In reality, the data I receive is of variable length, and I want to pass it onto a parser which determines the type of message that was received, from which node and based on that, chooses how to handle it further...

So, there is indeed no need to add it to the function like I did here, but I was hoping to get a clue why my train of thought was incorrect...

rappa

You should always use rx.getDataLength() when iterating through the packet.  It will always return the size of the payload.  The offset + 1 is from the droplet code and is used to skip the status byte.  I routinely send packets of up to 80 bytes so shouldn't be a size issue.

Go Up