The implementation of TCP/IP communication is presented. The interface is realized by creating a socket connection. For this purpose, the standard functionalities of JavaScript (in particular StreamWriter) are used.
1. Introduction
Sockets enable communication for data exchange between the robot and other network-accessible participants such as a facility or camera. This communication is bidirectional, meaning that data can be both received and transmitted.
This article describes how to establish communication using sockets and how to transfer data.
In this scenario, the robot acts as the client, and the counterpart acts as the server.
2. Establishing the Connection
To connect the robot to the counterpart, a network cable is used.
To establish the connection, you will need the IP address of the counterpart and the port. It is important to ensure that the IP addresses of both participants are in the same range. This means that the first 9 digits of the IP addresses must be the same, while the last 3 digits should be different.
If you need assistance with setting the IP address of the robot, you can refer to the following article: "Changing the IP Address".
You can use the following command to establish a connection using a socket. In this scenario, the robot acts as the client, while the counterpart acts as the server.
var IP_Adresse = "10.125.1.122";
var Port = 3000;
var socket = new java.net.Socket(IP_Adresse, Port);
The same process also works with a timeout feature.
var IP_Adresse = "10.125.1.122";
var Port = 3000;
var socket = new java.net.Socket();
socket.connect(new java.net.InetSocketAddress(IP_Adresse, Port), 10000); //10s timeout
3. Sending Information
You can use the following function to send a message as a string over the socket using a StreamWriter.
function schreibeNachricht(socket, nachricht)
{
var printWriter =
new java.io.PrintWriter(
new java.io.OutputStreamWriter(
socket.getOutputStream()));
printWriter.print(nachricht);
printWriter.flush();
}
The function is called using the following line of code. The desired message is passed as the second argument within the parentheses.
var Nachricht = "Hello World!";
schreibeNachricht(socket, Nachricht);
3.1. Sending raw data
If you need to send raw data, such as a hexadecimal byte array, over the socket, you can use the following function. This function allows you to easily transfer raw data between the robot and other network-accessible participants.
By utilizing this function, you can ensure efficient and accurate transmission of raw data.
function schreibeNachricht(socket, nachricht)
{
var jNachricht = Java.to(nachricht,"byte[]");
var dout = new java.io.DataOutputStream(socket.getOutputStream());
dout.write(jNachricht);
dout.flush();
}
The function is called using the following line of code. The desired message is passed as the second argument within the parentheses. In this case, the message "01hex 00hex 00hex 00hex" is being transmitted.
var connect_cam =[0x01, 0x00, 0x00, 0x00];
schreibeNachricht(socket, connect_cam);
4. Reading Information
To read a message as a string over the socket, you can use the following function with a StreamReader.
By utilizing this function, you can easily retrieve messages sent over the socket in a readable format.
function leseNachricht(socket)
{
var bufferedReader =
new java.io.BufferedReader(
new java.io.InputStreamReader(
socket.getInputStream()));
var charArrayType = Java.type("char[]");
var buffer = new charArrayType(200);
var anzahlZeichen = bufferedReader.read(buffer, 0, 200);
var nachricht = new java.lang.String(buffer);
return nachricht;
}
The function is called using the following line of code. The message is written into the variable 'result' and then displayed as a message in horstFX.
var result = leseNachricht(socket);
show_info(result);
4.1. Reading raw data
With the following function, you can read raw data encoded in decimal as a byte array over the socket. This allows for efficient transmission of raw data between the robot and other network-accessible participants.
function leseNachricht(socket, size)
{
var ByteArray = Java.type("byte[]");
var dIn = new java.io.DataInputStream(socket.getInputStream());
var message = new ByteArray(size);
dIn.readFully(message, 0, message.length);
var jsMessage = Java.from(message);
return jsMessage;
}
The function is called using the following line of code. The message is written into the variable 'result' and then displayed as a message in horstFX.
var result = leseNachricht(socket);
show_info(result);
4.2. Reading until a specific character (e.g., carriage return)
You can use the following function to read the socket until a defined character is encountered.
Often, a delimiter (such as a semicolon or newline) is added at the end of a transmitted string. With this function, the socket is continuously read until the specified delimiter is detected. This ensures that all the information has been transmitted.
function leseNachricht(socket, msgSperator)
{
var ByteHelper = Java.type("de.fruitcore.robot.core.util.ByteHelper");
var ByteArray = Java.type("byte[]");
var dIn = new java.io.DataInputStream(socket.getInputStream());
var full_msg = new ByteHelper();;
var buffer = new ByteArray(1);
while(1){
dIn.readFully(buffer, 0, buffer.length);
full_msg.putByte(buffer[0]);
if(msgSperator == buffer[0]){
break;
}
}
var nachricht = new java.lang.String(full_msg.toBytes(), java.nio.charset.StandardCharsets.UTF_8);
return nachricht;
}
The function is called using the following line of code. The variable 'delimiter' is used to define the separator until which the socket should be read. The message is then written into the variable 'result'.
var delimiter = "\r".charCodeAt(0); //Trennzeichen, z.B. CR Carriage Return (ggf. anpassen)
var result = leseNachricht(socket, delimiter);
4.3. Reading the message up to a specific timeout
To avoid the program getting stuck waiting for a message from the camera indefinitely, a timeout can be defined using the following line. This ensures that the program can be terminated if no message is received within a certain time.
// 10 sek Timeout when reading the message over a socket
socket.setSoTimeout(10000);
The function for reading the message can be modified as follows.
function leseNachricht(Socket) {
var bufferedReader =
new java.io.BufferedReader(
new java.io.InputStreamReader(
socket.getInputStream()));
var charArrayType = Java.type("char[]");
var buffer = new charArrayType(1000);
try {
var anzahlZeichen = bufferedReader.read(buffer, 0, 1000);
var nachricht = new java.lang.String(buffer);
} catch (e) {
var nachricht = "Timeout: Keine Nachricht erhalten";
}
return nachricht;
}
5. Ensuring the Socket is Closed
var IP_Adresse = "10.125.1.122";
var Port = 3000;
var socket = new java.net.Socket();
socket.connect(new java.net.InetSocketAddress(IP_Adresse, Port), 10000); //10s timeout
LOG.info("connected");
try {
//#############code begin#############
//#############code end #############
} finally {
socket.close();
}
The try-finally block ensures that the socket.close() function is called. This is useful in case of programming errors or when the cancel button is clicked. The entire logic should now be programmed between the ##code begin## and ##code end## markers. Additionally, it is important to define functions outside of the try-finally block.
6. Testing the Communication
To test the communication between the robot and other network-accessible participants, you can use various programs. Simply select the "Server" option and enter the IP address of the robot and the port number.
A basic program for socket connections can be used to facilitate this testing process.
One example of an application that utilizes TCP/IP communication is our Component Kit "SICK PLOC2D" for 2D part separation. You can find the documentation for this kit here.