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