RTDEClient.java 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package at.acdp.urweb.rtde;
  2. import at.acdp.urweb.rtde.packets.*;
  3. import org.slf4j.LoggerFactory;
  4. import java.io.DataInputStream;
  5. import java.io.DataOutputStream;
  6. import java.io.IOException;
  7. import java.net.Socket;
  8. import java.util.HashMap;
  9. import java.util.concurrent.Semaphore;
  10. import static at.acdp.urweb.rtde.CommandType.*;
  11. public class RTDEClient implements Runnable {
  12. private final static org.slf4j.Logger logger = LoggerFactory.getLogger(RTDEClient.class);
  13. private final Semaphore waitingRequestSem = new Semaphore(0);
  14. private volatile IRtdeData waitingRequest=null;
  15. public static int RTDE_PROTOCOL_VERSION = 2;
  16. private final String ip;
  17. private final int port;
  18. private volatile boolean _running = true;
  19. private volatile boolean initDone = false;
  20. private volatile DataOutputStream dos;
  21. private volatile DataInputStream dis;
  22. private Thread readThread;
  23. private RtdeSetupOutputs outputs;
  24. private HashMap<String, String> lastData;
  25. private RtdeSetupOutputs so;
  26. public RTDEClient(String ip, int port) {
  27. this.ip = ip;
  28. this.port = port;
  29. }
  30. public void start(RtdeSetupOutputs so) throws IOException, InterruptedException {
  31. this.so=so;
  32. readThread = new Thread(this);
  33. readThread.start();
  34. }
  35. public HashMap<String, String> getLastData() {
  36. return lastData;
  37. }
  38. public void request(IRtdeData data) throws IOException, InterruptedException {
  39. while(dos==null||dis==null) {
  40. Thread.sleep(100);
  41. }
  42. if(readThread.getId()==Thread.currentThread().getId()) {
  43. logger.error("request() must not be called from readThread.");
  44. }
  45. if(data.hasReply()) {
  46. waitingRequest=data;
  47. }
  48. data.send(dos);
  49. if(data.hasReply()) {
  50. waitingRequestSem.acquire();
  51. waitingRequest=null;
  52. }
  53. return;
  54. }
  55. private boolean init() throws IOException, InterruptedException {
  56. {
  57. var rpv = new RtdeRequestProtocolVersion();
  58. rpv.send(dos);
  59. int length = dis.readShort();
  60. int type = dis.readByte() & 0xFF;
  61. if(type!=RTDE_REQUEST_PROTOCOL_VERSION)
  62. return false;
  63. rpv.read(dis, length - 3);
  64. logger.info("RtdeRequestProtocolVersion succes:" + rpv.success);
  65. }
  66. {
  67. var ruv = new RtdeRequestURVersion();
  68. ruv.send(dos);
  69. int length=0;
  70. length = dis.readShort();
  71. int type = dis.readByte() & 0xFF;
  72. if(type!=RTDE_GET_URCONTROL_VERSION)
  73. return false;
  74. ruv.read(dis, length - 3);
  75. logger.info(String.format("RtdeRequestURVersion: %d.%d.%d.%d",ruv.major, ruv.minor, ruv.build, ruv.bugfix));
  76. }
  77. {
  78. so.send(dos);
  79. int length = dis.readShort();
  80. int type = dis.readByte() & 0xFF;
  81. if(type!=RTDE_CONTROL_PACKAGE_SETUP_OUTPUTS)
  82. return false;
  83. var r=so.read(dis, length - 1);
  84. logger.info("so:" +r.typesText);
  85. outputs=r;
  86. }
  87. {
  88. var start=new RtdeControlStart();
  89. start.send(dos);
  90. int length = dis.readShort();
  91. int type = dis.readByte() & 0xFF;
  92. if(type!=RTDE_CONTROL_PACKAGE_START)
  93. return false;
  94. start.read(dis, length -1);
  95. logger.info("start accepted:" +start.accepted);
  96. initDone=true;
  97. }
  98. return true;
  99. }
  100. private void handlePaket(int type, int length) throws IOException {
  101. var wreq=waitingRequest;
  102. if(wreq != null && type==wreq.getType()) {
  103. waitingRequest.read(dis, length-3);
  104. waitingRequestSem.release();
  105. } else switch(type) {
  106. case RTDE_TEXT_MESSAGE:
  107. var rpv = new RtdeTextMessage();
  108. rpv.read(dis, length-3);
  109. logger.info(String.format("RTDE_TEXT_MESSAGE: %s", rpv.text));
  110. break;
  111. case RTDE_DATA_PACKAGE:
  112. var p = new RtdeOutDataPackage(outputs);
  113. p.read(dis, length-3);
  114. lastData=p.getPdata();
  115. lastData.entrySet().forEach(entry->{
  116. logger.info(entry.getKey() + " " + entry.getValue());
  117. });
  118. break;
  119. default: {
  120. logger.warn(String.format("Unexpected package type: %d", type));
  121. byte[] buf=new byte[length];
  122. dis.readFully(buf);
  123. }
  124. }
  125. }
  126. @Override
  127. public void run() {
  128. while (_running) {
  129. initDone=false;
  130. try (Socket rt = new Socket(ip, port)){
  131. rt.setSoTimeout(10000);
  132. rt.setReuseAddress(true);
  133. rt.setTcpNoDelay(true);
  134. if (rt.isConnected()) {
  135. logger.info("Connected to UR Realtime Client");
  136. dos = new DataOutputStream(rt.getOutputStream());
  137. dis = new DataInputStream(rt.getInputStream());
  138. if(!init())
  139. throw new IOException("init failed");
  140. while (_running) {
  141. int length = dis.readShort();
  142. int type=dis.readByte() & 0xFF;
  143. handlePaket(type, length);
  144. }
  145. }
  146. } catch (IOException| InterruptedException e) {
  147. logger.warn("rtde connection closed", e);
  148. }
  149. }
  150. }
  151. }