package paramsim.paramicssimulator;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import paramsim.paramicssimulator.ParamicsSimulatorLogMessage.PARAMICS_SIMULATOR_LOG;
import paramsim.paramicssimulator.gui.ParamicsSimulatorGUI;
/**
* ParamicsSimulator is the main class for this module. The ParamicsSimulator
* can be used to simulate the Paramics device.
* The properties file for the ParamicsCommunicator class contains the following data.
*
* -----------------------------------------------------------------------------
* WorkingDirectory The working directory of the Paramics Communicator
* ParamicsStatusLog The Paramics status log file
* CameraStatusLog The camera status log file
* ExchangeLog The exchange log file
* CameraControlConfig The camera control file which maps the camera information
* DVDPlayersConfig The DVD Players XML file which contains camera information
* -----------------------------------------------------------------------------
* Example File:
* WorkingDirectory = c:/paramics/out
* ParamicsStatusLog = paramics_status.log
* CameraStatusLog = camera_status.log
* IncidentLog = exchange.log
* CameraControlConfig = camera_control.txt
* DVDPlayersConfig = dvdplayers.xml
* -----------------------------------------------------------------------------
*
*
* @author Greg Eddington (geddingt@calpoly.edu)
*/
public class ParamicsSimulator extends Observable implements Runnable
{
/** Error Log **/
private static Logger paramLogger = Logger.getLogger("paramsim.paramicssimulator");
/** Incident file **/
private static final String INCIDENT_FILE = "exchange.xml";
/** Paramics Status file **/
private static final String PARAM_STATUS_FILE = "paramics_status.xml";
/** Camera Status file **/
private static final String CAMERA_STATUS_FILE = "camera_status.xml";
/** Sleep Time (10 seconds) **/
private static final int SLEEP_TIME = 10000;
/**
* Enumeration containing property names.
* @author Greg Eddington
*/
private static enum PROPERTIES
{
/** The working directory for Paramics **/
WORKING_DIR ("WorkingDirectory"),
/** The Paramics log **/
PARAM_STATUS_LOG ("ParamicsStatusLog"),
/** The camera status log **/
CAMERA_STATUS_LOG ("CameraStatusLog"),
/** The exchange log **/
INCIDENT_LOG ("IncidentLog"),
/** The camera control file **/
CAMERA_CONTROL ("CameraControlConfig"),
/** The still images XML file **/
DVD_PLAYERS ("DVDPlayersConfig");
public String name;
private PROPERTIES(String n)
{
name = n;
}
}
/**
* Enumeration of network statuses.
* @author Greg Eddington
**/
public static enum NETWORK_STATUS
{
LOADING ("LOADING"),
WARMING ("WARMING"),
LOADED ("LOADED"),
UNKNOWN ("UNKNOWN");
public String message;
private NETWORK_STATUS(String n)
{
message = n;
}
}
/** Properties object. */
private Properties paramicsSimProp = null;
/** Working Directory **/
private String workingDirectory = null;
/** Incidents File **/
private String incidentFile = null;
/** Paramics Status File **/
private String paramStatusFile = null;
/** Camera Status File **/
private String cameraStatusFile = null;
/** Incidents Log **/
private String incidentLog = null;
/** Paramics Status Log **/
private String paramStatusLog = null;
/** Camera Status Log **/
private String cameraStatusLog = null;
/** Incident Reader **/
private ParamicsIncidentReader incidentReader = null;
/** The paramics simulator GUI **/
private ParamicsSimulatorGUI theGUI;
/** The network ID **/
private int networkId = 1;
/** Simulation Cameras **/
private List cameras;
/**
* Creates a ParamicsSimulator object with properties defined in the propertiesFile
* parameter. It will initialize all file locations.
*/
public ParamicsSimulator(String propertiesFile)
{
try
{
paramicsSimProp = new Properties();
paramicsSimProp.load(new FileInputStream(propertiesFile));
/** Check property file **/
for (PROPERTIES property : PROPERTIES.values())
{
if (paramicsSimProp.getProperty(property.name) == null ||
paramicsSimProp.getProperty(property.name).length() == 0)
{
System.err.println("Invalid Configuration: Properties file missing " +
property.name + " property.");
System.exit(0);
}
}
// Directory
workingDirectory = paramicsSimProp.getProperty(PROPERTIES.WORKING_DIR.name).trim();
boolean endsWithSlash = workingDirectory.charAt(workingDirectory.length()-1) == '/' ||
workingDirectory.charAt(workingDirectory.length()-1) == '\\';
// Files
paramStatusFile = workingDirectory + (endsWithSlash ? "" : "/") + PARAM_STATUS_FILE;
cameraStatusFile = workingDirectory + (endsWithSlash ? "" : "/") + CAMERA_STATUS_FILE;
incidentFile = workingDirectory + (endsWithSlash ? "" : "/") + INCIDENT_FILE;
// Logs
incidentLog = paramicsSimProp.getProperty(PROPERTIES.INCIDENT_LOG.name).trim();
paramStatusLog = paramicsSimProp.getProperty(PROPERTIES.PARAM_STATUS_LOG.name).trim();
cameraStatusLog = paramicsSimProp.getProperty(PROPERTIES.CAMERA_STATUS_LOG.name).trim();
// Delete any old logs
File ilFile = new File(incidentLog);
File pslFile = new File(paramStatusLog);
File cslFile = new File(cameraStatusLog);
ilFile.delete();
pslFile.delete();
cslFile.delete();
// Cameras
String cameraConfig = paramicsSimProp.getProperty(PROPERTIES.CAMERA_CONTROL.name).trim();
String stillImages = paramicsSimProp.getProperty(PROPERTIES.DVD_PLAYERS.name).trim();
try
{
// Load the cameras
cameras = CameraParser.loadCameras(stillImages, cameraConfig);
}
catch (IOException e)
{
// Create an empty camera array
cameras = new ArrayList();
// Log Error
paramLogger.logp(Level.SEVERE, "ParamicsSimulator", "Constructor",
"Error loading camera config from files \"" + stillImages +
"\" and \"" + cameraConfig + "\".", e);
}
// Initialize GUI
theGUI = new ParamicsSimulatorGUI(this);
addObserver(theGUI);
theGUI.addWindowListener
(
new WindowListener()
{
public void windowActivated(WindowEvent arg0) {};
public void windowClosed(WindowEvent arg0) {};
public void windowClosing(WindowEvent arg0) { System.exit(0); };
public void windowDeactivated(WindowEvent arg0) {};
public void windowDeiconified(WindowEvent arg0) {};
public void windowIconified(WindowEvent arg0) {};
public void windowOpened(WindowEvent arg0) {};
}
);
// Write an initial packets
writeParamicsStatus(NETWORK_STATUS.LOADING);
writeCameraStatus(cameras);
}
catch (Exception e)
{
paramLogger.logp(Level.SEVERE, "ParamicsSimulator", "Constructor",
"Exception in reading properties file.", e);
}
incidentReader = new ParamicsIncidentReader();
}
/**
* Appends a message to a log file.
* @param logName The name of the log file.
* @param message The message to append.
*/
private void writeToLog(String logName, String message)
{
try
{
FileWriter w = new FileWriter(logName, true);
w.write(message + "\n\n");
w.close();
}
catch (IOException e)
{
paramLogger.logp(Level.WARNING, "ParamicsSimulator", "writeToLog",
"Error writing to file " + logName + ".", e);
}
}
/**
* Runs the Paramics simulator thread.
*/
public void run()
{
// Check for packets and update the simulator
for(;;)
{
// Flush the input file
ParamicsSimulationInfo psi = incidentReader.parse(incidentFile);
// Update the network ID if a packet is received
if (psi != null)
{
networkId = psi.networkId;
writeToLog(incidentLog, psi.xmlMessage);
setChanged();
notifyObservers(new ParamicsSimulatorLogMessage(PARAMICS_SIMULATOR_LOG.EXCHANGE, psi.xmlMessage));
}
// Write camera status
writeCameraStatus(cameras);
// Sleep
try
{
Thread.sleep(SLEEP_TIME);
}
catch (InterruptedException ie) {}
}
}
/**
* Writes the camera status to the camera status XML file read by the Paramics Communicator,
* as well as to the camera status log file. All observers are notified with the new status,
* so they can also log it.
*
* @param id Camera ID
* @param route Route
* @param direction The direction of traffic
* @param postmile The postmile
* @param averageSpeedNE The average speed North or East
* @param averageSpeedSW The average speed South or West
*/
public void writeCameraStatus(List cameras)
{
StringBuilder message = new StringBuilder("\n");
for (SimulationCamera camera : cameras)
{
message.append
(
" \n" +
" " + camera.id + "\n" +
" " + camera.route + "\n" +
" " + camera.direction.xml + "\n" +
" " + camera.postmile + "\n" +
" " + camera.averageSpeedNE + "\n" +
" " + camera.averageSpeedSW + "\n" +
" \n"
);
}
message.append("");
try
{
FileWriter w = new FileWriter(cameraStatusFile);
w.write(message.toString());
w.close();
}
catch (IOException e)
{
paramLogger.logp(Level.SEVERE, "ParamicsSimulator", "writeCameraStatus",
"Error writing to file " + cameraStatusFile + ".", e);
}
writeToLog(cameraStatusLog, message.toString());
setChanged();
notifyObservers(new ParamicsSimulatorLogMessage(PARAMICS_SIMULATOR_LOG.CAMERA_STATUS, message.toString()));
}
/**
* Writes the Paramics status to the camera status XML file read by the Paramics Communicator,
* as well as to the Paramics status log file. All observers are notified with the new status,
* so they can also log it.
*
* @param status The current Paramics status
*/
public void writeParamicsStatus(NETWORK_STATUS status)
{
String message = "\n " + status.message +
"\n " + networkId + "\n";
try
{
FileWriter w = new FileWriter(paramStatusFile);
w.write(message);
w.close();
}
catch (IOException e)
{
paramLogger.logp(Level.SEVERE, "TrafficSimulator", "writeParamicsStatus",
"Error writing to file " + paramStatusFile + ".", e);
}
writeToLog(paramStatusLog, message);
setChanged();
notifyObservers(new ParamicsSimulatorLogMessage(PARAMICS_SIMULATOR_LOG.PARAMICS_STATUS, message));
}
/**
* Runs the Paramics simulator.
*/
public static void main(String[] args)
{
try
{
if(System.getProperty("PARAMICS_SIM_PROPERTIES") != null)
{
new Thread(new ParamicsSimulator(System.getProperty(
"PARAMICS_SIM_PROPERTIES"))).start();
}
else
{
throw new Exception ("PARAMICS_SIM_PROPERTIES system property not defined.");
}
}
catch (Exception e)
{
paramLogger.logp(Level.SEVERE, "ParamicsSimulator", "Main",
"Error occured initializing application", e);
JOptionPane.showMessageDialog(null, e.getMessage(), "Error - Program Exiting", JOptionPane.ERROR_MESSAGE);
System.exit(-1);
}
}
/**
* Gets the simulation cameras being used by the Paramics Simulator.
* @return A list of Simulation Cameras.
*/
public List getCameras()
{
return cameras;
}
}