1 package org.opentrafficsim.trafficcontrol.ccol;
2
3 import java.awt.Container;
4 import java.io.BufferedReader;
5 import java.io.IOException;
6 import java.io.InputStreamReader;
7 import java.io.PrintWriter;
8 import java.net.ServerSocket;
9 import java.net.Socket;
10 import java.util.Optional;
11 import java.util.Set;
12
13 import org.djunits.unit.DurationUnit;
14 import org.djunits.value.vdouble.scalar.Duration;
15 import org.djutils.event.Event;
16 import org.djutils.event.EventType;
17 import org.djutils.event.LocalEventProducer;
18 import org.djutils.exceptions.Try;
19 import org.opentrafficsim.base.logger.Logger;
20 import org.opentrafficsim.core.dsol.OtsSimulator;
21 import org.opentrafficsim.road.network.lane.object.detector.TrafficLightDetector;
22 import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLight;
23 import org.opentrafficsim.trafficcontrol.ActuatedTrafficController;
24 import org.opentrafficsim.trafficcontrol.TrafficControlException;
25
26 import nl.tudelft.simulation.dsol.SimRuntimeException;
27 import nl.tudelft.simulation.dsol.experiment.Replication;
28
29
30
31
32
33
34
35
36
37
38
39 public class Ccol extends LocalEventProducer implements ActuatedTrafficController
40 {
41
42 private final String id;
43
44
45 private final OtsSimulator simulator;
46
47
48 private static int port = 4321;
49
50
51 static final Duration EVALUATION_INTERVAL = new Duration(0.1, DurationUnit.SECOND);
52
53
54 private ServerSocket serverSocket;
55
56
57 private Socket clientSocket = null;
58
59
60 private BufferedReader ccolReader = null;
61
62
63 private PrintWriter ccolWriter = null;
64
65
66 private Thread acceptThread;
67
68
69
70
71
72
73
74
75
76
77
78
79
80 public Ccol(final String id, final String controlProgram, final Set<TrafficLight> trafficLights,
81 final Set<TrafficLightDetector> sensors, final OtsSimulator simulator)
82 throws TrafficControlException, SimRuntimeException
83 {
84 this.id = id;
85 this.simulator = simulator;
86 try
87 {
88
89 this.serverSocket = new ServerSocket(port);
90 Runnable acceptTask = new Runnable()
91 {
92 @Override
93 public void run()
94 {
95 try
96 {
97 setClientSocket(Ccol.this.serverSocket.accept());
98 }
99 catch (IOException exception)
100 {
101 exception.printStackTrace();
102 }
103 }
104 };
105 this.acceptThread = new Thread(acceptTask);
106 this.acceptThread.start();
107
108 Runtime.getRuntime().exec(controlProgram + " localhost:" + this.serverSocket.getLocalPort());
109 }
110 catch (IOException e)
111 {
112 e.printStackTrace();
113 }
114 this.simulator.scheduleEventRel(Duration.ZERO, () -> Try.execute(() -> step(), "Exception during Ccol step."));
115 this.simulator.addListener(this, Replication.END_REPLICATION_EVENT);
116 }
117
118
119
120
121
122 void setClientSocket(final Socket socket)
123 {
124 if (null != this.clientSocket)
125 {
126 Logger.ots().error("clientSocket already set");
127 return;
128 }
129 this.clientSocket = socket;
130 try
131 {
132 this.ccolReader = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
133 this.ccolWriter = new PrintWriter(this.clientSocket.getOutputStream());
134 }
135 catch (IOException exception)
136 {
137 exception.printStackTrace();
138 }
139
140 try
141 {
142 this.serverSocket.close();
143 }
144 catch (IOException exception)
145 {
146 exception.printStackTrace();
147 }
148 }
149
150
151
152
153
154 Socket getClientSocket()
155 {
156 return this.clientSocket;
157 }
158
159
160
161
162
163
164 @SuppressWarnings("unused")
165 private void step() throws TrafficControlException, SimRuntimeException
166 {
167
168 String message = String.format("STEP %s", this.simulator.getSimulatorTime());
169 this.ccolWriter.print(message);
170 try
171 {
172 String result = this.ccolReader.readLine();
173
174
175 }
176 catch (IOException exception)
177 {
178 exception.printStackTrace();
179 }
180
181 this.simulator.scheduleEventRel(EVALUATION_INTERVAL, () -> Try.execute(() -> step(), "Exception during Ccol step."));
182 }
183
184 @Override
185 public void notify(final Event event)
186 {
187 EventType eventType = event.getType();
188 if (eventType.equals(Replication.END_REPLICATION_EVENT))
189 {
190 if (null != this.serverSocket)
191 {
192 try
193 {
194 this.serverSocket.close();
195 }
196 catch (IOException exception)
197 {
198 exception.printStackTrace();
199 }
200 this.serverSocket = null;
201 }
202 if (null != this.clientSocket)
203 {
204 try
205 {
206 this.clientSocket.close();
207 }
208 catch (IOException exception)
209 {
210 exception.printStackTrace();
211 }
212 this.clientSocket = null;
213 }
214 }
215
216 }
217
218 @Override
219 public String getId()
220 {
221 return this.id;
222 }
223
224 @Override
225 public String getFullId()
226 {
227 return this.id;
228 }
229
230 @Override
231 public void updateDetector(final String detectorId, final boolean detectingGTU)
232 {
233
234 String message = String.format("DET %s %s", detectorId, detectingGTU);
235 this.ccolWriter.print(message);
236 }
237
238 @Override
239 public Optional<Container> getDisplayContainer()
240 {
241 return Optional.empty();
242 }
243
244 }