Es wird die Implementierung einer TCP/IP Kommunikation vorgestellt. Die Schnittstelle wird durch das Erstellen einer Socket-Verbindung realisiert. Hierf�r wird auf die Standardfunktionalit�ten von JavaScript (insb. StreamWriter) zur�ckgegriffen.
1. Einleitung
Mittels Sockets kann eine Kommunikation zum Datenaustausch zwischen dem Roboter und weiteren via Netzwerk erreichbaren Teilnehmern (Anlage, Kamera, etc.) hergestellt werden. Die Kommunikation erfolgt bidirektional. Das hei�t, Daten k�nnen empfangen sowie gesendet werden.
In dem folgenden Artikel wird beschrieben, wie eine solche Kommunikation �ber Sockets aufgebaut und Daten �bertragen werden k�nnen.
Der Roboter agiert hierbei als Client und die Gegenstelle als Server.
2. Aufbau der Verbindung
Der Roboter wird mittels eines Netzwerkkabels mit der Gegenstelle verbunden.
F�r den Verbindungsaufbau wird die IP-Adresse der Gegenstelle sowie der Port ben�tigt. Es ist darauf zu achten, dass die IP-Adressen der beiden Teilnehmer sich im selben Bereich befinden. Das hei�t, die vordersten 9 Stellen der IP-Adressen m�ssen gleich sein und die letzten 3 Stellen m�ssen sich voneinander unterscheiden.
In folgendem Artikel ist beschrieben, wie sich die IP-Adresse des Roboters einstellen l�sst. IP-Adresse �ndern
Mittels des folgenden Befehls kann eine Verbindung �ber einen Socket hergestellt werden. Der Roboter agiert hierbei als Client und die Gegenstelle als Server.
var IP_Adresse = "10.125.1.122";
var Port = 3000;
var socket = new java.net.Socket(IP_Adresse, Port);
Das gleiche funktioniert auch mit Timeout:
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. Informationen senden
Mittels der folgenden Funktion kann per StreamWriter eine Nachricht als Zeichenkette �ber den Socket gesendet werden.
function schreibeNachricht(socket, nachricht)
{
var printWriter =
new java.io.PrintWriter(
new java.io.OutputStreamWriter(
socket.getOutputStream()));
printWriter.print(nachricht);
printWriter.flush();
}
Die Funktion wird �ber folgende Zeile aufgerufen. In der Klammer wird als zweites Argument die gew�nschte Nachricht �bergeben.
var Nachricht = "Hello World!";
schreibeNachricht(socket, Nachricht);
3.1. Senden von raw-Daten
Sollen raw-Daten, zum Beispiel in Form eines hexadezimalen Byte Arrays, �ber den Socket gesendet werden, kann folgende Funktion genutzt werden.
function schreibeNachricht(socket, nachricht)
{
var jNachricht = Java.to(nachricht,"byte[]");
var dout = new java.io.DataOutputStream(socket.getOutputStream());
dout.write(jNachricht);
dout.flush();
}
Die Funktion wird �ber folgende Zeile aufgerufen. In der Klammer wird als zweites Argument die gew�nschte Nachricht �bergeben. Hierbei wird 01hex 00hex 00hex 00hex �bertragen.
var connect_cam =[0x01, 0x00, 0x00, 0x00];
schreibeNachricht(socket, connect_cam);
4. Informationen lesen
Mittels der folgenden Funktion kann per StreamReader eine Nachricht als Zeichenkette �ber den Socket gelesen werden.
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;
}
Die Funktion wird �ber folgende Zeile aufgerufen. In die Variable result wird die Nachricht geschrieben. Diese wird anschlie�end als Meldung in horstFX ausgegeben.
var result = leseNachricht(socket);
show_info(result);
4.1. Einlesen von raw-Daten
Mittels der folgenden Funktion k�nnen raw-Daten dezimal codiert als Byte-Array �ber den Socket gelesen werden.
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;
}
Die Funktion wird �ber folgende Zeile aufgerufen. In die Variable result wird die Nachricht geschrieben. Diese wird anschlie�end als Meldung in horstFX ausgegeben.
var result = leseNachricht(socket);
show_info(result);
4.2. Einlesen bis zu einem bestimmten Zeichen (z.B. carriage return)
Mittels der folgenden Funktion kann die Socket bis zu einem definierten Zeichen ausgelesen werden.
Oft wird am Ende eines zu �bertragenden Strings ein Trennzeichen (Semikolon, Zeilenumbruch, etc.) geschrieben. Mit der folgenden Funktion wird die Socket solange ausgelesen, bis das definierte Trennzeichen erkannt/eingelesen wurde. Dadurch wird sichergestellt, dass die gesamten Informationen �bertragen wurden.
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;
}
Die Funktion wird �ber folgende Zeile aufgerufen. In der Variable delimiter wird das Trennzeichen definiert, bis zu dem die Socket ausgelesen werden soll. In die Variable result wird die Nachricht geschrieben.
var delimiter = "\r".charCodeAt(0); //Trennzeichen, z.B. CR Carriage Return (ggf. anpassen)
var result = leseNachricht(socket, delimiter);
4.3. Einlesen der Nachricht bis zu einem bestimmten Timeout
Ein Timeout, falls einige Zeit keine Nachricht von der Kamera gesendet wird, kann �ber folgende Zeile definiert werden. Ansonsten k�nnte das Programm nicht abgebrochen werden, da der Roboter st�ndig auf die Nachricht wartet.
// 10 sek Timeout beim Einlesen der Nachricht ueber einen Socket
socket.setSoTimeout(10000);
Die Funktion zum Einlesen der Nachricht kann dazu folgenderma�en angepasst werden.
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. Sicherstellen, dass der Socket geschlossen wird
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();
}
Durch den try finally Block wird sichergestellt, das socket.close() aufgerufen wird. Das Funktioniert bei Programmierfehlern oder auch beim Abbrechen �ber den Abbrechen-Button.
Die gesamte Logik muss nun zwischen ##code begin## und ##code end ## Programmiert werden. Au�erdem muss darauf geachtet werden, dass Funktionen au�erhalb des try finally Block�s definiert werden.
6. Testen der Kommunikation
Mittels verschiedener Programme l�sst sich die Kommunikation sehr einfach testen. Es muss lediglich Server ausgew�hlt sowie die IP-Adresse des Roboters und der Port eingetragen werden.
Basis Progamm f�r Socketverbindungen
Ein Anwendungsbeispiel f�r eine TCP/IP Kommunikation ist unser Component Kit "SICK PLOC2D" f�r die Teilevereinzelung im 2D Bereich. Die Dokumentation finden Sie hier.