When using languages other than C++ with NML, there are several problems. The header files with the NML message definitions can not be included. The libraries for managing the NML communications are not available. In the case of a Java applet the NML configuration file might also not be available. One solution to this problem is to link together C++ code with the code written in another language into a single program. This was the approach used in the EMC Graphical User Interface which is primarily written in Visual Basic. Another approach is that the program written in non-C++ connect via sockets to an NML server. However because the NML server has many options writing the client might require a great deal of work to support all the options. Here I will choose a set of options that simplifies the interface for a Java client and describe how the client can be written.
On each buffer line for buffers remove any of the following if they were there: (TCP=?, UDP=?, ascii, xdr).
Then add "STCP=
To open a connection create a new socket, making sure to match the host and port from the NML configuration file.
String host = "giskard.cme.nist.gov"; int port = 2001; Socket nmlsocket; nmlSocket = new Socket(host, port);
Then create a DataInputStream and DataOutputStream using that socket.
DataOutputStream nmlOs; DataInputStream nmlIs; nmlOs = new DataOutputStream(nmlSocket.GetOutputStream); nmlIs = new DataInputStream(nmlSocket.GetInputStream);
To read from an NML buffer, write "read:\n" or "peek:" to the DataOutputStream, then read a line from the DataInputStream. The line will contain the NML message beginning with the type and size of the message and followed by members in the order the update functions are called. (The size indicates the size of the structure in C++ not the length of the string returned. -- Ignore it.) The parameters are separated by commas. Below is an example of how to parse this string.
// Receive the current position. String nmlMsgString; long type; long size; float x; int index; nmlOs.writeBytes("read:\n"); nmlMsgString = nmlIs.ReadLine(); // nmlMsgString might look like this "8010,32,5.0,-25.0,0.7" type = (Long.valueOf(nmlMsgString)).longValue(); index = nmlMsgString.indexOf(","); size = (Long.valueOf(nmlMsgString.substring(index))).longValue(); index = nmlMsgString.indexOf(",",index); x = (Float.valueOf(nmlMsgString.substring(index))).floatValue();To write to a NML buffer send write "write:" or "write_if_read:" followed by the message in the same form as they are read in, beginning with the type and size followed by members separated by commas. It is not necessary to provide all of the members of the message. Members omitted from the end of the string will be considered to be zero. It is also not necessary to calculate the size of the message, but a place holder is necessary if there are any other members to set in the string.
// Send the command to goto x,0,0 nmlOs.writeBytes("8001,0," + (new Double(x)).toString());
This example consists of 3 programs:
The applet looks somewhat like a stopwatch. The controller doesn't have any hardware to control so I simulate world model by just updating the time in the world model buffer. Since we lack the computing resources here to run a separate controller for each user that starts the applet, pressing reset, start, or stop changes not only your display but also the display of anyone else viewing this applet.
Viewing the applet has been disabled as it can't be supported on our new webserver.
Last Modified: 08/25/99
If you have questions or comments regarding this page or you would like to be notified of changes to the RCS library via email, please contact Will Shackleford at shackle@cme.nist.gov