| 1 | package tmcsim.cadsimulator.managers; |
|---|
| 2 | |
|---|
| 3 | import java.io.FileInputStream; |
|---|
| 4 | import java.io.IOException; |
|---|
| 5 | import java.util.Properties; |
|---|
| 6 | import java.util.logging.Level; |
|---|
| 7 | import java.util.logging.Logger; |
|---|
| 8 | import tmcsim.cadmodels.CMSInfo; |
|---|
| 9 | import tmcsim.cadsimulator.Coordinator; |
|---|
| 10 | import tmcsim.cadsimulator.paramicscontrol.ParamicsCameraStatusReader; |
|---|
| 11 | import tmcsim.cadsimulator.paramicscontrol.ParamicsCommunicator; |
|---|
| 12 | import tmcsim.cadsimulator.paramicscontrol.ParamicsIncidentWriter; |
|---|
| 13 | import tmcsim.cadsimulator.paramicscontrol.ParamicsStatusReader; |
|---|
| 14 | import tmcsim.common.CADEnums.PARAMICS_STATUS; |
|---|
| 15 | import tmcsim.common.SimulationException; |
|---|
| 16 | import tmcsim.common.XMLIncident; |
|---|
| 17 | |
|---|
| 18 | /** |
|---|
| 19 | * ParamicsSimulationManager is a CAD Simulator Manager used to handle all |
|---|
| 20 | * communication between the CAD Simulator and the remote ParamicsCommunicator. |
|---|
| 21 | * Upon construction all ParamicsReaders and ParamicsWriters are initialized |
|---|
| 22 | * with data parsed from the Properties file. When a connection is established |
|---|
| 23 | * the ParamicsStatusReader is registered to read Paramics Status updates. These |
|---|
| 24 | * updates are received through the updateParamicsStatus() method, which |
|---|
| 25 | * notifies the Coordinator of the new status. The loadParamicsNetwork() must be |
|---|
| 26 | * called to register the ParamicsIncidentWriter which will write the |
|---|
| 27 | * information to cause Paramics to begin loading a traffic network. When the |
|---|
| 28 | * status becomes LOADED, the ParamicsCameraStatusReader is registered and |
|---|
| 29 | * begins reading. All camera speed updates are received through the |
|---|
| 30 | * updateCameraInfo() method. The startSimulation(), resetSimulation(), and |
|---|
| 31 | * sendIncidentUpdate() methods are used to control the flow of Incident update |
|---|
| 32 | * information to Paramics. The updateIncident() and updateDiversion() methods |
|---|
| 33 | * are used to update the information that is sent to Paramics. |
|---|
| 34 | * |
|---|
| 35 | * |
|---|
| 36 | * @see PARAMICS_STATUS |
|---|
| 37 | * @author Matthew Cechini |
|---|
| 38 | * @version |
|---|
| 39 | */ |
|---|
| 40 | public class ParamicsSimulationManager |
|---|
| 41 | { |
|---|
| 42 | |
|---|
| 43 | /** |
|---|
| 44 | * Error logger. |
|---|
| 45 | */ |
|---|
| 46 | private static Logger paramLogger = Logger.getLogger("tmcsim.cadsimulator.paramicscontrol"); |
|---|
| 47 | |
|---|
| 48 | /** |
|---|
| 49 | * Enumeration containing property names for Properties parsing. |
|---|
| 50 | * |
|---|
| 51 | * @author Matthew Cechini |
|---|
| 52 | */ |
|---|
| 53 | private static enum PROPERTIES |
|---|
| 54 | { |
|---|
| 55 | |
|---|
| 56 | PARAMICS_HOST("ParamicsCommHost"), |
|---|
| 57 | PARAMICS_PORT("ParamicsCommPort"), |
|---|
| 58 | INCIDENT_UPDATE_INT("IncidentUpdateInterval"), |
|---|
| 59 | INCIDENT_UPDATE_FILE("IncidentUpdateFile"), |
|---|
| 60 | PARAMICS_STATUS_INT("ParamicsStatusInterval"), |
|---|
| 61 | PARAMICS_STATUS_FILE("ParamicsStatusFile"), |
|---|
| 62 | CAMERA_STATUS_INT("CameraStatusInterval"), |
|---|
| 63 | CAMERA_STATUS_FILE("CameraStatusFile"); |
|---|
| 64 | String name; |
|---|
| 65 | |
|---|
| 66 | private PROPERTIES(String n) |
|---|
| 67 | { |
|---|
| 68 | name = n; |
|---|
| 69 | } |
|---|
| 70 | }; |
|---|
| 71 | /** |
|---|
| 72 | * ParamicsCommunicator Object used for communication. |
|---|
| 73 | */ |
|---|
| 74 | private ParamicsCommunicator theCommunicator; |
|---|
| 75 | /** |
|---|
| 76 | * Reference to the Coordinator Object. |
|---|
| 77 | */ |
|---|
| 78 | private Coordinator theCoordinator; |
|---|
| 79 | /** |
|---|
| 80 | * Reference to the MediaManager Object. |
|---|
| 81 | */ |
|---|
| 82 | private MediaManager theMediaMgr; |
|---|
| 83 | /** |
|---|
| 84 | * ParamicsIncidentWriter used to send incident updates to Paramics. |
|---|
| 85 | */ |
|---|
| 86 | private ParamicsIncidentWriter paramicsIncidentWriter; |
|---|
| 87 | /** |
|---|
| 88 | * ParamicsStatusReader used to read status information from Paramics. |
|---|
| 89 | */ |
|---|
| 90 | private ParamicsStatusReader paramicsStatusReader; |
|---|
| 91 | /** |
|---|
| 92 | * ParamicsCameraStatusReader used to read speed information from Paramics. |
|---|
| 93 | */ |
|---|
| 94 | private ParamicsCameraStatusReader paramicsCameraStatusReader; |
|---|
| 95 | /** |
|---|
| 96 | * Properties file. |
|---|
| 97 | */ |
|---|
| 98 | private Properties paramicsProperties; |
|---|
| 99 | |
|---|
| 100 | /** |
|---|
| 101 | * Constructor. Loads the Properties file and initializes all Paramics |
|---|
| 102 | * Writers and Readers with the parsed data. |
|---|
| 103 | * |
|---|
| 104 | * @param propertiesFile Target file path of properties file. |
|---|
| 105 | * @param coor Coordinator Object. |
|---|
| 106 | * @param mediaMgr MediaManager Object. |
|---|
| 107 | */ |
|---|
| 108 | public ParamicsSimulationManager(String propertiesFile, Coordinator coor, MediaManager mediaMgr) |
|---|
| 109 | { |
|---|
| 110 | |
|---|
| 111 | try |
|---|
| 112 | { |
|---|
| 113 | paramicsProperties = new Properties(); |
|---|
| 114 | paramicsProperties.load(new FileInputStream(propertiesFile)); |
|---|
| 115 | |
|---|
| 116 | theCoordinator = coor; |
|---|
| 117 | theMediaMgr = mediaMgr; |
|---|
| 118 | |
|---|
| 119 | theCommunicator = new ParamicsCommunicator(this, |
|---|
| 120 | paramicsProperties.getProperty(PROPERTIES.PARAMICS_HOST.name), |
|---|
| 121 | Integer.parseInt(paramicsProperties.getProperty( |
|---|
| 122 | PROPERTIES.PARAMICS_PORT.name).trim())); |
|---|
| 123 | |
|---|
| 124 | paramicsIncidentWriter = new ParamicsIncidentWriter(Integer.parseInt( |
|---|
| 125 | paramicsProperties.getProperty(PROPERTIES.INCIDENT_UPDATE_INT.name).trim())); |
|---|
| 126 | paramicsIncidentWriter.writerID = theCommunicator.nextID(); |
|---|
| 127 | paramicsIncidentWriter.targetFile = paramicsProperties.getProperty( |
|---|
| 128 | PROPERTIES.INCIDENT_UPDATE_FILE.name); |
|---|
| 129 | |
|---|
| 130 | paramicsStatusReader = new ParamicsStatusReader(this); |
|---|
| 131 | paramicsStatusReader.readerID = theCommunicator.nextID(); |
|---|
| 132 | paramicsStatusReader.interval = paramicsProperties.getProperty( |
|---|
| 133 | PROPERTIES.PARAMICS_STATUS_INT.name).trim(); |
|---|
| 134 | paramicsStatusReader.targetFile = paramicsProperties.getProperty( |
|---|
| 135 | PROPERTIES.PARAMICS_STATUS_FILE.name); |
|---|
| 136 | |
|---|
| 137 | paramicsCameraStatusReader = new ParamicsCameraStatusReader(this); |
|---|
| 138 | paramicsCameraStatusReader.readerID = theCommunicator.nextID(); |
|---|
| 139 | paramicsCameraStatusReader.interval = paramicsProperties.getProperty( |
|---|
| 140 | PROPERTIES.CAMERA_STATUS_INT.name).trim(); |
|---|
| 141 | paramicsCameraStatusReader.targetFile = paramicsProperties.getProperty( |
|---|
| 142 | PROPERTIES.CAMERA_STATUS_FILE.name); |
|---|
| 143 | } catch (Exception e) |
|---|
| 144 | { |
|---|
| 145 | paramLogger.logp(Level.SEVERE, "ParamicsSimulationManager", |
|---|
| 146 | "Constructor", "Exception in parsing properties file.", e); |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | } |
|---|
| 150 | |
|---|
| 151 | /** |
|---|
| 152 | * Returns whether a connection exists to the remote ParamicsCommunicator. |
|---|
| 153 | * |
|---|
| 154 | * @return true if a connection exists, false if not. |
|---|
| 155 | */ |
|---|
| 156 | public boolean isConnected() |
|---|
| 157 | { |
|---|
| 158 | return theCommunicator.isConnected(); |
|---|
| 159 | } |
|---|
| 160 | |
|---|
| 161 | /** |
|---|
| 162 | * Returns the integer Network ID that has been loaded into Paramics. |
|---|
| 163 | * |
|---|
| 164 | * @return Network ID. |
|---|
| 165 | */ |
|---|
| 166 | public int getParamicsNetworkLoaded() |
|---|
| 167 | { |
|---|
| 168 | return paramicsStatusReader.getNetworkID(); |
|---|
| 169 | } |
|---|
| 170 | |
|---|
| 171 | /** |
|---|
| 172 | * Returns the current status of the Paramics traffic modeler. |
|---|
| 173 | * |
|---|
| 174 | * @return Current PARAMICS_STATUS |
|---|
| 175 | */ |
|---|
| 176 | public PARAMICS_STATUS getParamicsStatus() |
|---|
| 177 | { |
|---|
| 178 | return paramicsStatusReader.getStatus(); |
|---|
| 179 | } |
|---|
| 180 | |
|---|
| 181 | /** |
|---|
| 182 | * Updates the ParamicsIncidentWriter with new Incident information. |
|---|
| 183 | * |
|---|
| 184 | * @param xmlInc Updated Incident information. |
|---|
| 185 | */ |
|---|
| 186 | public void updateIncident(XMLIncident xmlInc) |
|---|
| 187 | { |
|---|
| 188 | paramicsIncidentWriter.updateIncident(xmlInc); |
|---|
| 189 | } |
|---|
| 190 | |
|---|
| 191 | /** |
|---|
| 192 | * Updates the ParamicsIncidentWriter with the new Diversion information. |
|---|
| 193 | * |
|---|
| 194 | * @param theDiversion Updated diversion information. |
|---|
| 195 | */ |
|---|
| 196 | public void updateDiversion(CMSInfo theDiversion) |
|---|
| 197 | { |
|---|
| 198 | paramicsIncidentWriter.updateDiversion(theDiversion); |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | /** |
|---|
| 202 | * Notifies the ParamicsIncidentWriter to start the simulation. |
|---|
| 203 | */ |
|---|
| 204 | public void startSimulation() |
|---|
| 205 | { |
|---|
| 206 | paramicsIncidentWriter.startSimulation(); |
|---|
| 207 | } |
|---|
| 208 | |
|---|
| 209 | /** |
|---|
| 210 | * Notifies the ParamicsIncidentWriter to reset the simulation. |
|---|
| 211 | */ |
|---|
| 212 | public void resetSimulation() |
|---|
| 213 | { |
|---|
| 214 | paramicsIncidentWriter.resetSimulation(); |
|---|
| 215 | } |
|---|
| 216 | |
|---|
| 217 | /** |
|---|
| 218 | * Notifies the ParamicsIncidentWriter to send an Incident update. |
|---|
| 219 | * |
|---|
| 220 | * @param currentSimTime Current simulation time (in seconds). |
|---|
| 221 | */ |
|---|
| 222 | public void sendIncidentUpdate(long currentSimTime) |
|---|
| 223 | { |
|---|
| 224 | paramicsIncidentWriter.sendUpdate(currentSimTime); |
|---|
| 225 | } |
|---|
| 226 | |
|---|
| 227 | /** |
|---|
| 228 | * Establish a connection to the remote ParamicsCommunicator. Register the |
|---|
| 229 | * ParamicsStatusReader and update the current status to CONNECTED. If an |
|---|
| 230 | * exception occurs in connecting to the ParamicsCommunicator, update the |
|---|
| 231 | * current status to UNREACHABLE. |
|---|
| 232 | */ |
|---|
| 233 | public void connectToParamics() |
|---|
| 234 | { |
|---|
| 235 | try |
|---|
| 236 | { |
|---|
| 237 | theCommunicator.connect(); |
|---|
| 238 | theCommunicator.registerReader(paramicsStatusReader); |
|---|
| 239 | |
|---|
| 240 | updateParamicsStatus(PARAMICS_STATUS.CONNECTED); |
|---|
| 241 | } catch (IOException ioe) |
|---|
| 242 | { |
|---|
| 243 | paramLogger.logp(Level.SEVERE, "Coordinator", "connectToParamics", |
|---|
| 244 | "Communication error in connecting to Paramics.", ioe); |
|---|
| 245 | |
|---|
| 246 | updateParamicsStatus(PARAMICS_STATUS.UNREACHABLE); |
|---|
| 247 | } |
|---|
| 248 | } |
|---|
| 249 | |
|---|
| 250 | /** |
|---|
| 251 | * Close the connection to the remote ParamicsCommunicator. Unregister all |
|---|
| 252 | * Readers and Wrtiers from the ParamicsCommunicator. Reset the status |
|---|
| 253 | * information in the ParamicsStatusReader. Update the current status to |
|---|
| 254 | * DISCONNECTED. |
|---|
| 255 | */ |
|---|
| 256 | public void disconnectFromParamics() |
|---|
| 257 | { |
|---|
| 258 | |
|---|
| 259 | theCommunicator.disconnect(); |
|---|
| 260 | theCommunicator.unregisterReader(paramicsStatusReader); |
|---|
| 261 | theCommunicator.unregisterWriter(paramicsIncidentWriter); |
|---|
| 262 | theCommunicator.unregisterReader(paramicsCameraStatusReader); |
|---|
| 263 | |
|---|
| 264 | paramicsStatusReader.resetStatusInfo(); |
|---|
| 265 | |
|---|
| 266 | updateParamicsStatus(PARAMICS_STATUS.DISCONNECTED); |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | /** |
|---|
| 270 | * Updates the current paramics status. If the new status is LOADED, then |
|---|
| 271 | * notify the ParamicsIncidentWriter that the network has been loaded and |
|---|
| 272 | * register the ParamicsCameraStatusReader with the ParamicsCommunicator. |
|---|
| 273 | * Notify the Coordinator of all Paramics status updates. |
|---|
| 274 | * |
|---|
| 275 | * @param newStatus New Paramics status. |
|---|
| 276 | */ |
|---|
| 277 | public void updateParamicsStatus(PARAMICS_STATUS newStatus) |
|---|
| 278 | { |
|---|
| 279 | |
|---|
| 280 | //the network has finished loading |
|---|
| 281 | if (newStatus == PARAMICS_STATUS.LOADED) |
|---|
| 282 | { |
|---|
| 283 | |
|---|
| 284 | paramicsIncidentWriter.networkLoaded(); |
|---|
| 285 | |
|---|
| 286 | theCommunicator.registerReader(paramicsCameraStatusReader); |
|---|
| 287 | |
|---|
| 288 | } else if (newStatus == PARAMICS_STATUS.DROPPED) |
|---|
| 289 | { |
|---|
| 290 | paramLogger.logp(Level.WARNING, "Coordinator", "updateParamicsStatus", |
|---|
| 291 | "Connection to Paramics has been dropped."); |
|---|
| 292 | } |
|---|
| 293 | |
|---|
| 294 | theCoordinator.setParamicsStatus(newStatus); |
|---|
| 295 | |
|---|
| 296 | } |
|---|
| 297 | |
|---|
| 298 | /** |
|---|
| 299 | * If a connection has been made, register the ParamicsIncidentWriter and |
|---|
| 300 | * use it to notify Paramics of the Network ID to load. |
|---|
| 301 | * |
|---|
| 302 | * @param networkID Network ID to load. |
|---|
| 303 | * @throws SimulationException if a connection has not been made to the |
|---|
| 304 | * remote ParamicsCommunicator. |
|---|
| 305 | */ |
|---|
| 306 | public void loadParamicsNetwork(int networkID) throws SimulationException |
|---|
| 307 | { |
|---|
| 308 | |
|---|
| 309 | if (theCommunicator.isConnected()) |
|---|
| 310 | { |
|---|
| 311 | theCommunicator.registerWriter(paramicsIncidentWriter); |
|---|
| 312 | paramicsIncidentWriter.loadNetwork(networkID); |
|---|
| 313 | } else |
|---|
| 314 | { |
|---|
| 315 | throw new SimulationException(SimulationException.PARAMICS_NOT_CONNECTED); |
|---|
| 316 | } |
|---|
| 317 | } |
|---|
| 318 | |
|---|
| 319 | /** |
|---|
| 320 | * Receive updated camera speed information. Notify the MediaManager with |
|---|
| 321 | * the updated data. |
|---|
| 322 | * |
|---|
| 323 | * @param cameraID CCTV camera ID |
|---|
| 324 | * @param avgSpeed_NE Average speed of traffic flowing N or E |
|---|
| 325 | * @param avgSpeed_SW Average speed of traffic flowing S or W |
|---|
| 326 | */ |
|---|
| 327 | public void updateCameraInfo(Integer cameraID, float avgSpeed_NE, float avgSpeed_SW) |
|---|
| 328 | { |
|---|
| 329 | theMediaMgr.updateCameraInfo(cameraID, avgSpeed_NE, avgSpeed_SW); |
|---|
| 330 | } |
|---|
| 331 | } |
|---|