View Javadoc
1   package org.opentrafficsim.demo;
2   
3   import java.io.BufferedReader;
4   import java.io.ByteArrayOutputStream;
5   import java.io.IOException;
6   import java.io.InputStream;
7   import java.io.InputStreamReader;
8   import java.io.OutputStream;
9   import java.net.Socket;
10  import java.net.URL;
11  import java.net.URLConnection;
12  import java.nio.charset.StandardCharsets;
13  import java.util.stream.Collectors;
14  
15  import org.opentrafficsim.aimsun.proto.AimsunControlProtoBuf;
16  
17  import com.google.protobuf.CodedOutputStream;
18  
19  import nl.tudelft.simulation.language.io.URLResource;
20  
21  /**
22   * Test client for AimsunController.
23   * <p>
24   * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
25   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
26   * <p>
27   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Apr 18, 2017 <br>
28   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
29   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
30   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
31   */
32  public final class TestController
33  {
34      /**
35       * Cannot be instantiated.
36       */
37      private TestController()
38      {
39          // Do not instantiate.
40      }
41  
42      /**
43       * Test client for AimsunControl.
44       * <p>
45       * (c) copyright 2002-2018 <a href="http://www.simulation.tudelft.nl">Delft University of Technology</a>. <br>
46       * BSD-style license. See <a href="http://www.simulation.tudelft.nl/dsol/3.0/license.html">DSOL License</a>. <br>
47       * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
48       * @version Oct 21, 2016
49       */
50      /**
51       * @param args command line arguments
52       * @throws IOException when communication fails
53       */
54      public static void main(final String[] args) throws IOException
55      {
56          String ip = null;
57          Integer port = null;
58  
59          for (String arg : args)
60          {
61              int equalsPos = arg.indexOf("=");
62              if (equalsPos < 0)
63              {
64                  System.err.println("Unhandled argument \"" + arg + "\"");
65              }
66              String key = arg.substring(0, equalsPos);
67              String value = arg.substring(equalsPos + 1);
68              switch (key.toUpperCase())
69              {
70                  case "IP":
71                      ip = value;
72                      break;
73                  case "PORT":
74                      try
75                      {
76                          port = Integer.parseInt(value);
77                      }
78                      catch (NumberFormatException exception)
79                      {
80                          System.err.println("Bad port number \"" + value + "\"");
81                          System.exit(1);
82                      }
83                      break;
84                  default:
85                      System.err.println("Unhandled argument \"" + arg + "\"");
86              }
87          }
88          if (null == ip || null == port)
89          {
90              System.err.println("Missing required argument(s) ip=<ip-number_or_hostname> port=<port-number>");
91              System.exit(1);
92          }
93          // Construct the create simulation command (including the network description in XML
94          AimsunControlProtoBuf.CreateSimulation.Builder createSimulationBuilder =
95                  AimsunControlProtoBuf.CreateSimulation.newBuilder();
96          createSimulationBuilder.setRunTime(3600d);
97          createSimulationBuilder.setWarmUpTime(0d);
98          // String network = URLResource.getResource("/aimsun/singleRoad.xml").toString(); // wrong; fix later
99          String networkResource = "/aimsun/singleRoad.xml";
100         String network = null; // IOUtils.toString(URLResource.getResource(networkResource));
101         URL networkURL = URLResource.getResource(networkResource);
102         if (null == networkURL)
103         {
104             throw new Error("Could not load network from resource " + networkResource);
105         }
106         URLConnection conn = networkURL.openConnection();
107         try (BufferedReader reader =
108                 new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)))
109         {
110             network = reader.lines().collect(Collectors.joining("\n"));
111         }
112 
113         // Socket to talk to server
114         System.out.println("Connecting to server...");
115         Socket socket = new Socket(ip, port);
116         System.out.println("Connected");
117         OutputStream outputStream = socket.getOutputStream();
118         InputStream inputStream = socket.getInputStream();
119         // Send a create simulation command
120         createSimulationBuilder.setNetworkXML(network);
121         System.out.println("Sending CREATESIMULATION message");
122         sendProtoMessage(outputStream,
123                 AimsunControlProtoBuf.OTSMessage.newBuilder().setCreateSimulation(createSimulationBuilder.build()).build());
124         // Simulate 10 seconds in 0.5 second steps
125         for (int step = 0; step <= 20; step++)
126         {
127             AimsunControlProtoBuf.SimulateUntil simulateUntil =
128                     AimsunControlProtoBuf.SimulateUntil.newBuilder().setTime(0.5d * step).build();
129             System.out.println("Sending simulate up to step " + step + " command");
130             sendProtoMessage(outputStream, AimsunControlProtoBuf.OTSMessage.newBuilder().setSimulateUntil(simulateUntil)
131                     .build());
132             System.out.println("Receive reply");
133             AimsunControlProtoBuf.OTSMessage reply = receiveProtoMessage(inputStream);
134             System.out.println("Received " + reply);
135         }
136         try
137         {
138             Thread.sleep(5000);
139         }
140         catch (InterruptedException exception)
141         {
142             exception.printStackTrace();
143         }
144         socket.close();
145     }
146 
147     /**
148      * Transit one message to the OTS server.
149      * @param outputStream OutputStream; output stream to the OTS server
150      * @param message AimsunControlProtobuf.OTSMessage; the message
151      * @throws IOException when communication fails in any way
152      */
153     public static void sendProtoMessage(final OutputStream outputStream, final AimsunControlProtoBuf.OTSMessage message)
154             throws IOException
155     {
156         int size = message.getSerializedSize();
157         // System.out.println("About to transmit message of " + size + " bytes");
158         byte[] sizeBytes = new byte[4];
159         sizeBytes[0] = (byte) ((size >> 24) & 0xff);
160         sizeBytes[1] = (byte) ((size >> 16) & 0xff);
161         sizeBytes[2] = (byte) ((size >> 8) & 0xff);
162         sizeBytes[3] = (byte) (size & 0xff);
163         outputStream.write(sizeBytes);
164         ByteArrayOutputStream baos = new ByteArrayOutputStream();
165         message.writeTo(CodedOutputStream.newInstance(baos));
166         // byte[] buffer = new byte[size];
167         // buffer = message.toByteArray();
168         outputStream.write(baos.toByteArray());
169         // System.out.println("Done");
170     }
171 
172     /**
173      * Read one OTSMessage.
174      * @param inputStream InputStream; input stream to read from
175      * @return OTSMessage; the OTSMessage that was constructed from the read bytes
176      * @throws IOException when communication fails
177      */
178     public static AimsunControlProtoBuf.OTSMessage receiveProtoMessage(final InputStream inputStream) throws IOException
179     {
180         byte[] sizeBytes = receiveBytes(inputStream, 4);
181         // for (int i = 0; i < 4; i++)
182         // {
183         // System.out.print(String.format("%d ", sizeBytes[i]));
184         // }
185         int size =
186                 ((sizeBytes[0] & 0xff) << 24) + ((sizeBytes[1] & 0xff) << 16) + ((sizeBytes[2] & 0xff) << 8)
187                         + (sizeBytes[3] & 0xff);
188         // System.out.println(String.format("-> %d", size));
189         byte[] messageBytes = receiveBytes(inputStream, size);
190         return AimsunControlProtoBuf.OTSMessage.parseFrom(messageBytes);
191     }
192 
193     /**
194      * Read a specified number of bytes.
195      * @param inputStream InputStream; input stream to read from
196      * @param size int; number of bytes to read
197      * @return byte[]; byte array filled with the read bytes
198      * @throws IOException when communication fails
199      */
200     public static byte[] receiveBytes(final InputStream inputStream, final int size) throws IOException
201     {
202         System.out.print("Need to read " + size + " bytes ... ");
203         int offset = 0;
204         byte[] buffer = new byte[size];
205         while (true)
206         {
207             int bytesRead = inputStream.read(buffer, offset, buffer.length - offset);
208             if (-1 == bytesRead)
209             {
210                 break;
211             }
212             offset += bytesRead;
213             if (buffer.length == offset)
214             {
215                 System.out.println("Got all " + buffer.length + " requested bytes");
216                 break;
217             }
218             if (buffer.length < offset)
219             {
220                 System.out.println("Oops: Got more than " + buffer.length + " requested bytes");
221                 break;
222             }
223             System.out.print("Now got " + offset + " bytes; need to read " + (buffer.length - offset) + " more bytes ");
224         }
225         if (offset != buffer.length)
226         {
227             throw new IOException("Got only " + offset + " of expected " + buffer.length + " bytes");
228         }
229         return buffer;
230     }
231 
232 }