package art.servers.etdserver.controller;
|
|
|
import art.library.interop.InteropParameter;
|
import art.library.interop.InteropParameters;
|
import art.library.interop.InteropResponse;
|
import art.library.model.devices.DeviceStatus;
|
import art.library.model.devices.etd.Etd;
|
import art.library.interop.serialization.Serialization;
|
import art.library.interop.serialization.SerializationException;
|
import art.library.model.devices.Device;
|
import art.library.model.devices.DevicePersistenceTimeless;
|
import art.library.model.devices.application.Application;
|
import art.library.model.devices.etd.EtdInformation;
|
import art.library.model.devices.etd.EtdStatus;
|
import art.library.model.devices.etd.information.EtdInformationSection;
|
import art.library.model.devices.etd.status.EtdStatusLane;
|
import art.library.model.transactions.traces.Trace;
|
import art.library.utils.common.NumberUtils;
|
import art.library.utils.synchro.Mutex;
|
import art.servers.ServerException;
|
import art.servers.etdserver.Shared;
|
import static java.lang.Thread.sleep;
|
import java.net.Socket;
|
import java.text.SimpleDateFormat;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.List;
|
|
|
public class ControllerMController extends ControllerEtd
|
{
|
private SimpleDateFormat sdh = new SimpleDateFormat("HH:mm");
|
private Socket socket = null;
|
private boolean connected = false;
|
private long lastTimestamp = 0;
|
private int status = DeviceStatus.STATUS_ALARM;
|
private boolean firstTime = true;
|
private List<EtdStatus> letdStatus = new ArrayList<EtdStatus>();
|
private String serverAddress = "";
|
private int serverPort = 0;
|
private int serverTimeout = 30000;
|
private Mutex mutexEtdStatus = new Mutex();
|
|
|
public ControllerMController(Etd etd)
|
{
|
super(etd);
|
this.device = etd;
|
this.name = Shared.getMessage("Controller etd") + " " + etd.information.name;
|
}
|
|
|
|
|
public void run()
|
{
|
String message = Shared.getMessage("Running");
|
// <editor-fold defaultstate="collapsed" desc="Trace">
|
art.servers.Shared.println(Trace.getTraceInformation(art.servers.Shared.getApplicationName(), name, art.servers.Shared.getMessage("Starting"), art.servers.Shared.getMessage("Success")), true);
|
// </editor-fold>
|
status = DeviceStatus.STATUS_ONLINE;
|
|
while ((isInterrupted() == false) && (exit == false))
|
{
|
long startTimestamp = System.currentTimeMillis();
|
|
try
|
{
|
if (art.servers.Shared.isServerEnabled() == true)
|
{
|
getColorsServer();
|
|
if (connected == false)
|
{
|
connect();
|
}
|
|
update();
|
}
|
}
|
catch (Exception e)
|
{
|
e.printStackTrace();
|
}
|
|
if (startTimestamp > System.currentTimeMillis())
|
{
|
startTimestamp = System.currentTimeMillis();
|
}
|
|
long stopTimestamp = startTimestamp + (device.getDeviceInformation().polling * 1000);
|
|
while ((System.currentTimeMillis() < stopTimestamp) && (exit == false))
|
{
|
try
|
{
|
sleep(50);
|
}
|
catch (Exception e)
|
{
|
}
|
}
|
|
if (art.servers.Shared.model.existsDevice(device.getIdentifier()) == false)
|
{
|
art.servers.Shared.println(name, art.servers.Shared.getMessage("Device no longer exists"));
|
exit = true;
|
}
|
}
|
|
// <editor-fold defaultstate="collapsed" desc="Trace">
|
art.servers.Shared.println(Trace.getTraceInformation(art.servers.Shared.getApplicationName(), name, art.servers.Shared.getMessage("Finishing"), art.servers.Shared.getMessage("Success")), true);
|
// </editor-fold>
|
}
|
|
|
public EtdStatus[] getRealtimeTrafficData (long timestamp1, long timestamp2)
|
{
|
List<EtdStatus> list = new ArrayList<EtdStatus>();
|
|
try
|
{
|
mutexEtdStatus.lockRead();
|
|
for (EtdStatus etdStatus : letdStatus)
|
{
|
if ((timestamp1 <= etdStatus.measurementTimestamp) && (etdStatus.measurementTimestamp <= timestamp2))
|
{
|
list.add(etdStatus);
|
}
|
}
|
}
|
catch (Exception e)
|
{
|
|
}
|
finally
|
{
|
mutexEtdStatus.releaseRead();
|
}
|
|
return(list.toArray(new EtdStatus[0]));
|
}
|
|
|
|
|
/*
|
Private controller functions
|
*/
|
|
private void getColorsServer()
|
{
|
try
|
{
|
List<Device> ldevice = (List<Device>)DevicePersistenceTimeless.getDevices((List<Object>)(List<?>)Shared.controllerDatabase.timeless_getObject(DevicePersistenceTimeless.class.getName(), "type = '" + Application.class.getName() + "'"));
|
|
for (Device device : ldevice)
|
{
|
if (device instanceof Application)
|
{
|
Application application = (Application)device;
|
if (application.getDeviceInformation().serverServiceName.equalsIgnoreCase("colors") == true)
|
{
|
String serverAddress = application.getDeviceInformation().serverAddress;
|
int serverPort = application.getDeviceInformation().serverPort;
|
if ((this.serverAddress.equalsIgnoreCase(serverAddress) == false) || (this.serverPort != serverPort))
|
{
|
disconnect();
|
}
|
|
this.serverAddress = serverAddress;
|
this.serverPort = serverPort;
|
}
|
}
|
}
|
}
|
catch (Exception e)
|
{
|
// If any error, we continues with last serverAddress and serverPort values
|
}
|
}
|
|
|
private EtdStatus getRealtimeTrafficData() throws ServerException, SerializationException, Exception
|
{
|
InteropParameters parameters = new InteropParameters();
|
parameters.addParameter(new InteropParameter("service", name));
|
parameters.addParameter(new InteropParameter("operation", "getRealtimeTrafficData"));
|
parameters.addParameter(new InteropParameter("language", Shared.configuration.general.language));
|
parameters.addParameter(new InteropParameter("identifier", this.device.getIdentifier().replaceAll("etd-", "")));
|
parameters.addParameter(new InteropParameter("timestamp", String.valueOf(lastTimestamp)));
|
InteropResponse response = (InteropResponse)Serialization.invoke("get", parameters, socket);
|
EtdStatus[] etdStatus = Arrays.copyOf(response.getValue(), response.getValue().length, EtdStatus[].class);
|
|
lastTimestamp = etdStatus[0].measurementTimestamp;
|
|
return(etdStatus[0]);
|
}
|
|
|
private void update() throws Exception
|
{
|
Etd etdclone = (Etd)Serialization.clone(device);
|
|
try
|
{
|
EtdStatus etdStatus = getRealtimeTrafficData();
|
|
updateEtdStatus(etdclone, etdStatus);
|
|
addEtdStatus(etdclone.getDeviceStatus());
|
|
online(etdclone);
|
return;
|
}
|
catch (Exception exception)
|
{
|
Shared.printstack(name, exception);
|
if ((etdclone.alarms.alarm_offline <= 0) || (firstTime == true))
|
{
|
firstTime = false;
|
String message = art.servers.Shared.getMessage("Etd offline");
|
art.servers.Shared.println(name, exception);
|
}
|
|
offline(etdclone);
|
try{disconnect();} catch (Exception ex){};
|
}
|
}
|
|
|
|
|
private void offline(Etd etdclone)throws Exception
|
{
|
if (etdclone.getAlarm("alarm_offline") <= 0)
|
{
|
etdclone.getDeviceAlarms().clear();
|
}
|
|
etdclone.setAlarm("alarm_offline", true);
|
Shared.model.updateDevice(device, etdclone);
|
}
|
|
|
private void online(Etd etdclone) throws Exception
|
{
|
if ((etdclone.alarms.alarm_offline > 0) || (firstTime == true))
|
{
|
firstTime = false;
|
String message = art.servers.Shared.getMessage("Etd online");
|
art.servers.Shared.println(name, message);
|
}
|
|
etdclone.setAlarm("alarm_offline", false);
|
etdclone.setAlarm("alarm_invalid", false);
|
Shared.model.updateDevice(device, etdclone);
|
}
|
|
|
private void addEtdStatus (EtdStatus etdStatus)
|
{
|
try
|
{
|
mutexEtdStatus.lockWrite();
|
|
if (letdStatus.size() == this.device.getDeviceInformation().realTimeSavingPeriods)
|
{
|
letdStatus.remove(0);
|
}
|
|
letdStatus.add(etdStatus);
|
}
|
catch (Exception e)
|
{
|
|
}
|
finally
|
{
|
mutexEtdStatus.releaseWrite();
|
}
|
}
|
|
|
private void updateEtdStatus (Etd etdclone, EtdStatus etdStatusController)
|
{
|
try
|
{
|
EtdStatus etdStatusCurrent = etdclone.getDeviceStatus();
|
etdStatusCurrent.measurementTimestamp = etdStatusController.measurementTimestamp;
|
etdStatusCurrent.period = etdclone.getDeviceInformation().period;
|
etdStatusCurrent.llane.clear();
|
etdStatusCurrent.llane = etdStatusController.llane;
|
|
etdStatusCurrent.lsection.clear();
|
|
if (etdStatusCurrent.total == null)
|
{
|
etdStatusCurrent.total = new EtdStatusLane();
|
}
|
|
emptyTotal(etdclone, etdStatusCurrent);
|
etdStatusCurrent.total.status = DeviceStatus.STATUS_OFFLINE;
|
|
for (EtdStatusLane laneStatus : etdStatusCurrent.llane)
|
{
|
addLaneToTotal(laneStatus, etdStatusCurrent);
|
List<EtdInformationSection> lsectionInformation = getSectionInformationLane(etdclone.getDeviceInformation(), laneStatus.number);
|
for (EtdInformationSection sectionInformation : lsectionInformation)
|
{
|
EtdStatusLane sectionStatus = etdStatusCurrent.getSection(sectionInformation.number);
|
if (sectionStatus == null)
|
{
|
sectionStatus = new EtdStatusLane();
|
sectionStatus.number = sectionInformation.number;
|
sectionStatus.status = DeviceStatus.STATUS_OFFLINE;
|
etdStatusCurrent.lsection.add(sectionStatus);
|
}
|
|
addLaneToSection(laneStatus, sectionStatus);
|
}
|
}
|
|
// Adjust Total and Sections values
|
if (etdStatusCurrent.total.counting > 0)
|
{
|
etdStatusCurrent.total.speed = (int)(etdStatusCurrent.total.speed / etdStatusCurrent.total.counting);
|
etdStatusCurrent.total.length = (etdStatusCurrent.total.length / etdStatusCurrent.total.counting);
|
etdStatusCurrent.total.distance = (etdStatusCurrent.total.speed / etdStatusCurrent.total.counting);
|
etdStatusCurrent.total.occupancy = (etdStatusCurrent.total.occupancy / etdStatusCurrent.total.counting);
|
etdStatusCurrent.total.occupancy = NumberUtils.ajustarDecimales(etdStatusCurrent.total.occupancy, 1);
|
etdStatusCurrent.total.length = NumberUtils.ajustarDecimales((float)(etdStatusCurrent.total.length/10d), 1);
|
etdStatusCurrent.total.distance = NumberUtils.ajustarDecimales((float)etdStatusCurrent.total.distance, 1);
|
if (etdStatusCurrent.total.occupancy > 100) etdStatusCurrent.total.occupancy = 100;
|
if (etdStatusCurrent.total.occupancy < 0) etdStatusCurrent.total.occupancy = 0;
|
if (etdStatusCurrent.total.length < 0) etdStatusCurrent.total.length = 0;
|
if (etdStatusCurrent.total.distance < 0) etdStatusCurrent.total.distance = 0;
|
if (etdStatusCurrent.total.speed < 0) etdStatusCurrent.total.speed = 0;
|
}
|
|
for (EtdStatusLane sectionStatus : etdStatusCurrent.lsection)
|
{
|
sectionStatus.speed = (int)(sectionStatus.speed / sectionStatus.counting);
|
sectionStatus.length = (sectionStatus.length / sectionStatus.counting);
|
sectionStatus.distance = (sectionStatus.speed / sectionStatus.counting);
|
sectionStatus.occupancy = (sectionStatus.occupancy / sectionStatus.counting);
|
sectionStatus.occupancy = NumberUtils.ajustarDecimales(sectionStatus.occupancy, 1);
|
sectionStatus.length = NumberUtils.ajustarDecimales((float)(sectionStatus.length/10d), 1);
|
sectionStatus.distance = NumberUtils.ajustarDecimales((float)sectionStatus.distance, 1);
|
if (sectionStatus.occupancy > 100) sectionStatus.occupancy = 100;
|
if (sectionStatus.occupancy < 0) sectionStatus.occupancy = 0;
|
if (sectionStatus.length < 0) sectionStatus.length = 0;
|
if (sectionStatus.distance < 0) sectionStatus.distance = 0;
|
if (sectionStatus.speed < 0) sectionStatus.speed = 0;
|
}
|
}
|
catch (Exception e)
|
{
|
e.printStackTrace();
|
}
|
}
|
|
|
private void connect()
|
{
|
try
|
{
|
if (socket != null)
|
{
|
if (this.connected == true)
|
{
|
return;
|
}
|
}
|
|
socket = new Socket(serverAddress, serverPort);
|
socket.setSoTimeout(serverTimeout);
|
this.connected = true;
|
}
|
catch (Exception e)
|
{
|
try{disconnect();} catch (Exception ex){};
|
}
|
}
|
|
|
|
|
private void disconnect() throws ServerException, Exception
|
{
|
try { socket.close(); }catch (Exception e) {}
|
socket = null;
|
this.connected = false;
|
}
|
|
|
|
|
private List<EtdInformationSection> getSectionInformationLane (EtdInformation etdInformation, int lane)
|
{
|
List<EtdInformationSection> lresult = new ArrayList<EtdInformationSection>();
|
|
for (EtdInformationSection sectionInformation : etdInformation.lSection)
|
{
|
for (Integer number : sectionInformation.llane)
|
{
|
if ((number.intValue()) == lane) lresult.add(sectionInformation);
|
}
|
}
|
|
return(lresult);
|
}
|
|
|
private void addLaneToTotal (EtdStatusLane laneStatus, EtdStatus etdStatus)
|
{
|
etdStatus.total.totalMeasurements += 1;
|
|
if (laneStatus.status == DeviceStatus.STATUS_ONLINE)
|
{
|
etdStatus.total.status = DeviceStatus.STATUS_ONLINE;
|
etdStatus.total.correctMeasurements += 1;
|
etdStatus.total.counting += laneStatus.counting;
|
etdStatus.total.speed += (laneStatus.counting*laneStatus.speed);
|
etdStatus.total.occupancy += (laneStatus.counting*laneStatus.occupancy);
|
etdStatus.total.length += (laneStatus.counting*laneStatus.length);
|
etdStatus.total.distance += (laneStatus.counting*laneStatus.distance);
|
etdStatus.total.unclassified += laneStatus.unclassified;
|
for (int i=0; i<etdStatus.total.lengths.length; i++) etdStatus.total.lengths[i] += laneStatus.lengths[i];
|
for (int i=0; i<etdStatus.total.speeds.length; i++) etdStatus.total.speeds[i] += laneStatus.speeds[i];
|
for (int i=0; i<etdStatus.total.speedxlength.length; i++)
|
{
|
for (int j=0; j<etdStatus.total.speedxlength[i].length; j++)
|
etdStatus.total.speedxlength[i][j] += laneStatus.speedxlength[i][j];
|
}
|
|
if (laneStatus.congestionDetection == true)
|
etdStatus.total.congestionDetection = true;
|
if (laneStatus.wrongWayVehicleDetection == true)
|
etdStatus.total.wrongWayVehicleDetection = true;
|
}
|
}
|
|
|
private void addLaneToSection (EtdStatusLane laneStatus, EtdStatusLane sectionStatus)
|
{
|
sectionStatus.status = DeviceStatus.STATUS_ONLINE;
|
sectionStatus.correctMeasurements += 1;
|
sectionStatus.totalMeasurements += 1;
|
sectionStatus.counting += laneStatus.counting;
|
sectionStatus.speed += (laneStatus.counting*laneStatus.speed);
|
sectionStatus.occupancy += (laneStatus.counting*laneStatus.occupancy);
|
sectionStatus.length += (laneStatus.counting*laneStatus.length);
|
sectionStatus.distance += (laneStatus.counting*laneStatus.distance);
|
sectionStatus.unclassified += laneStatus.unclassified;
|
for (int i=0; i<sectionStatus.lengths.length; i++) sectionStatus.lengths[i] += laneStatus.lengths[i];
|
for (int i=0; i<sectionStatus.speeds.length; i++) sectionStatus.speeds[i] += laneStatus.speeds[i];
|
for (int i=0; i<sectionStatus.speedxlength.length; i++)
|
{
|
for (int j=0; j<sectionStatus.speedxlength[i].length; j++)
|
sectionStatus.speedxlength[i][j] += laneStatus.speedxlength[i][j];
|
}
|
|
if (laneStatus.congestionDetection == true)
|
sectionStatus.congestionDetection = true;
|
if (laneStatus.wrongWayVehicleDetection == true)
|
sectionStatus.wrongWayVehicleDetection = true;
|
}
|
|
|
private void emptyTotal (Etd etdclone, EtdStatus etdStatus)
|
{
|
etdStatus.total.totalMeasurements = 0;
|
etdStatus.total.correctMeasurements = 0;
|
etdStatus.total.status = DeviceStatus.STATUS_OFFLINE;
|
etdStatus.total.counting = 0;
|
etdStatus.total.speed = 0;
|
etdStatus.total.occupancy = 0;
|
etdStatus.total.length = 0;
|
etdStatus.total.distance = 0;
|
etdStatus.total.unclassified = 0;
|
etdStatus.total.congestionDetection = false;
|
etdStatus.total.wrongWayVehicleDetection = false;
|
etdStatus.total.lengths = new int[etdclone.getDeviceInformation().lLengthClassification.size()];
|
for (int l=0; l<etdStatus.total.lengths.length; l++)
|
etdStatus.total.lengths[l] = 0;
|
etdStatus.total.speeds = new int[etdclone.getDeviceInformation().lSpeedClassification.size()];
|
for (int s=0; s<etdStatus.total.speeds.length; s++)
|
etdStatus.total.speeds[s] = 0;
|
etdStatus.total.speedxlength = new int[etdclone.getDeviceInformation().lSpeedClassification.size()][etdclone.getDeviceInformation().lLengthClassification.size()];
|
for (int s=0; s<etdStatus.total.speeds.length; s++)
|
{
|
for (int l=0; l<etdStatus.total.lengths.length; l++)
|
{
|
etdStatus.total.speedxlength[s][l] = 0;
|
}
|
}
|
}
|
|
}
|