The third MOOS variable type

While we usually thing of MOOS variables as having only two types - double and string - a third type called "binary string" is also defined.  While any string can hold binary data, the character 0x00 is special and usually used to indicate the end of a string.  That means if you tried to send some binary data that contained the byte 0x00 in the middle using a normal string MOOS variable, everything after the 0x00 would be lost.  A binary string MOOS variable keeps track of its data length separately so it knows to keep looking for data after the 0x00.  

To be clear, both string and binary string MOOS variables are storing their data using the string container.  Here we use italics to differentiate the MOOS variable types from the C++ container.  Any string can hold binary data, including 0x00 and in most cases putting 0x00 in a string will not be an issue when you're just doing it in your own program.  0x00 is only treated as a special character by certain functions such as strlen and other carry overs from C.  It's only when you want to send that data through MOOS that you need to be concerned about what type of MOOS variable it's going into.  

iacomms_driver has two input variables to transmit data - ACOMMS_TRANSMIT_DATA and ACOMMS_TRANSMIT_DATA_BINARY.  As expected, the first is a string variable and the second a binary string.  You can still post binary data to ACOMMS_TRANSMIT_DATA as long as there isn't an 0x00.  Both messages are handled identically inside the driver.  

Implementation

First we look at how to post binary data to a MOOS variable.  The type of MOOS variable you post depends on how you call the Notify() method.  

// some data we want to send
vector<unsigned char> packet;
packet.push_back(0x61);
packet.push_back(0x00);
packet.push_back(0x62);

// binary string - pass a pointer to Notify along with the size 
m_Comms.Notify( "ACOMMS_TRANSMIT_DATA_BINARY", &packet[0], packet.size() );

// string - convert to a string and pass to Notify
m_Comms.Notify( "ACOMMS_TRANSMIT_DATA", string( (char*) &packet[0], packet.size() ) );

In the first method we get a binary string MOOS variable by passing Notify() a pointer to our data along with the size of the data.  In the second method we pass Notify() a string, so we get a string MOOS variable.  Using the code above, ACOMMS_TRANSMIT_DATA_BINARY will contain our complete data - 0x61,0x00,0x62 - whereas ACOMMS_TRANSMIT_DATA will only contain 0x61.  iacomms_driver posts to both of these variables when it starts up, so if you try to post the wrong format in your program it simply won't get posted.  

Reading binary data is simple because you can simply use GetString() whether the MOOS variable is a string or binary string.  Once you have a string, the .data() method will give you a pointer to the data itself inside the string that you can then use with methods like memcpy.  See endianness and data serialization for more.

  • No labels