OpenJAUS

Sending and Receiving Messages

!!! 3.3.0a CRITICAL UPDATE !!!

JAUS messages are used to communicate information to and from a system component. The OpenJAUS library provides components with a set of functions to send and receive JAUS messages. All messages to and from an OpenJAUS component are in the form of the JausMessage data type. The OpenJAUS message library contains the functions that transform a generic JausMessage into a specific message form, i.e. QueryGlobalPose, ReportComponentStatus, etc. These functions must be used in order to explicitly access the data within a specific JAUS message type. The message library also defines specific data structures for each of the standard JAUS messages, and functions to create and destroy those data structures.

Creating a JAUS message of a specific type is done by invoking its create function. This will allocate the memory required for the message and return the data structure containing the message fields. Each message data structure also contains all of the fields defined for the standard JAUS message header. Creating and setting up a message is done on a type by type basis. The fields for a particular message type can be found by looking at its cooresponding header file in libjaus. This is an example of how to create and setup a ReportGlobalPoseMessage.
ReportGlobalPoseMessage myReportGposMsg;			// Declare the message variable

myReportGposMsg = reportGlobalPoseMessageCreate();		// Create the message

// Clear all presence vector bits
myReportGposMsg->presenceVector = 0;

// Turn on only latitude and longitude bits
jausUnsignedShortSetBit(&myReportGposMsg->presenceVector, JAUS_POSE_PV_LATITUDE_BIT);
jausUnsignedShortSetBit(&myReportGposMsg->presenceVector,  JAUS_POSE_PV_LONGITUDE_BIT);

myReportGposMsg->latitudeDegrees = 29.646190;			// Set the latitude of the reported location
myReportGposMsg->longitudeDegrees = -82.349187;			// Set the longitude of the reported location
When the component is finished with a message, it simply calls the corresponding destroy() function.
reportGlobalPoseMessageDestroy(myReportGposMsg);
Sending JAUS a message from a component is done by calling the function ojCmptSendMessage(). When this function is called the JAUS message source address is automatically set to that of the sending component's. However, the message destination address must be explicitly set before sending the message. Typically when a specific type of JAUS message needs to be sent, it first must be cast into the generic type form. The sudo-code block below shows the pattern usually implemented to send a specific message. Notice that the jausMessage must be destroyed after it is sent. This is because memory allocated for the jausMessage during the specificMessageToJausMessage() step must be freed after it is no longer needed.
jausAddressCopy(mySpecificMessage->destination, someAddress);		// Copy destination address into message

jausMessage = specificMessageToJausMessage(mySpecificMessage);		// Convert specific message type into JausMessage type

ojCmptSendMessage(myComponent, jausMessage);				// Send the message via the component and node manager

jausMessageDestroy(jausMessage);					// Free allocated memory
Receiving a JAUS message in a component is done by setting up a callback function for the specific message command code. After the OjCmpt is running, the callback function will be invoked upon receiving a message with that command code. If no callback function is registered for a command code, the message is automatically processed by the ojCmptDefaultMessageProcessor() function. This function handles most of the core functionality of a JAUS component. This includes processing incoming commands for authority, state, exclusive control, service connections and discovery (See defaultJausMessageProcessor.c in libopenJaus to identify the implemented command codes and their associated default behavior). If a message is not processed in the default message processor then it is simply ignored. It is possible to override the default message processor by explicitly registering a callback function for the desired command code. If the default behavior needs to be extended, then a registered callback can execute its behavior and also pass the message to ojCmptDefaultMessageProcessor().

Message callback functions must follow the prototype form "void callbackname(OjCmpt, JausMessage);". Registration of the callback function with the component is usually done between the ojCmptCreate() step and the ojCmptRun() step (See Creating an OpenJAUS component for details on these steps). The function to register the message callback is ojCmptSetMessageCallback(). The following example shows how this would be done for a JAUS_QUERY_GLOBAL_POSE message.
void myQueryGlobalPoseCallback(OjCmpt myGpos, JausMessage queryMessage);		// Function prototype of message callback

ojCmptSetMessageCallback(myGpos, JAUS_QUERY_GLOBAL_POSE, myQueryGlobalPoseCallback);	// Register the callback function with the myGpos component
The message callback function implementation is responsible for converting the JausMessage type into the type of the specific message. The following example shows how the response to a query GPOS message might be implemented.

!!! 3.3.0a CRITICAL UPDATE !!!
You no longer destroy the JausMessage sent to the callback function. This has been removed to keep a one-to-one create and destroy function ratio within your code. Calling the jausMessageDestroy() on the incomming JausMessage will produce a double-free memory exception, so you must remove it from your code. The example below shows the line of code that needs to be removed. It is commented in the example, but for correctness you should simply delete it from your software.
void myQueryGlobalPoseCallback(OjCmpt myGpos, JausMessage message)			// Query global pose message callback function
{
	JausMessage txMessage;
	QueryGlobalPoseMessage queryGlobalPose;
	
	queryGlobalPose = queryGlobalPoseMessageFromJausMessage(message);		// Parse the message into its queryGloablPose message form
	if(queryGlobalPose)						// Verify there are no errors in parsing
	{
		jausAddressCopy(myReportGposMsg->destination, queryGlobalPose->source);		// Copy the source to destination
		
		txMessage = reportGlobalPoseMessageToJausMessage(myReportGposMsg);		// Serialize the report global pose message response
		ojCmptSendMessage(myGpos, txMessage);						// Send the report response
		jausMessageDestroy(txMessage);						// Destroy the sent JausMessage
		
		queryGlobalPoseMessageDestroy(queryGlobalPose);				// Destroy the query message
	}
	else					
	{
		printf("Error unpacking JAUS_QUERY_GLOBAL_POSE\n");
	}
	
	//jausMessageDestroy(message); !!! CRITICAL UPDATE !!! remove this line of code from your 3.3.0 software
}

 

© OpenJAUS.com 2008
All Rights Reserved