package art.servers.etdserver.historical;
|
|
import art.library.interop.serialization.Serialization;
|
import art.library.model.devices.Device;
|
import art.library.model.devices.DevicePersistenceHistorical;
|
import art.library.model.devices.DeviceStatus;
|
import art.library.model.devices.etd.Etd;
|
import art.library.model.devices.etd.EtdStatus;
|
import art.library.model.devices.etd.status.EtdStatusAggregation;
|
import art.library.model.devices.etd.status.EtdStatusAggregationLane;
|
import art.library.model.devices.etd.status.EtdStatusLane;
|
import art.servers.ServerException;
|
import art.servers.Shared;
|
import java.sql.ResultSet;
|
import java.util.ArrayList;
|
import java.util.Calendar;
|
import java.util.HashMap;
|
|
|
|
public class HistoricalPeriods
|
{
|
private Etd etd = null;
|
private String identifier = null;
|
private int lane = -1;
|
private int section = -1;
|
private long timestamp1 = 0;
|
private long timestamp2 = 0;
|
private String name = null;
|
|
private String language = null;
|
private int aggregationPeriod = 0;
|
private int etdPeriod = 0;
|
private int numberOfPeriods = 0;
|
private Register register = null;
|
private EtdStatus[] lEtdStatus = new EtdStatus[0];
|
|
|
public HistoricalPeriods(String identifier, int lane, int section, long timestamp1, long timestamp2, int aggregationPeriod, String language)
|
{
|
Calendar calendar1 = Calendar.getInstance();
|
calendar1.setTimeInMillis(timestamp1);
|
calendar1.set(Calendar.SECOND,0);
|
calendar1.set(Calendar.MILLISECOND,0);
|
|
Calendar calendar2 = Calendar.getInstance();
|
calendar2.setTimeInMillis(timestamp2);
|
calendar2.set(Calendar.SECOND,0);
|
calendar2.set(Calendar.MILLISECOND,0);
|
|
this.identifier = identifier;
|
this.lane = lane;
|
this.section = section;
|
this.timestamp1 = calendar1.getTimeInMillis();
|
this.timestamp2 = calendar2.getTimeInMillis();
|
this.aggregationPeriod = aggregationPeriod;
|
this.language = language;
|
}
|
|
|
|
|
public EtdStatusAggregation generate() throws ServerException
|
{
|
ResultSet result = null;
|
|
|
try
|
{
|
long timestampStart = this.timestamp1 - (300000L);
|
long timestampEnd = this.timestamp2 + (600000L);
|
String command = "SELECT value FROM DEVICES WHERE identifier = '" + identifier + "' AND type = '" + Etd.class.getName() + "' AND timestamp >= " + timestampStart + " AND timestamp < " + timestampEnd + " ORDER BY timestamp ASC";
|
|
String message = "From " + Device.getDate(timestamp1) + " to " + Device.getDate(timestamp2);
|
Shared.println("Historical", message);
|
Shared.println("Historical", command);
|
|
result = Shared.controllerDatabase.getHistoricalPersistance().get(0).executeQuery(command);
|
|
while (result.next() == true)
|
{
|
String value = result.getString(1);
|
|
if (etd == null)
|
{
|
etd = (Etd)((DevicePersistenceHistorical)Serialization.deserialize(DevicePersistenceHistorical.class, value)).device;
|
if (etd != null)
|
{
|
initialise();
|
}
|
}
|
else
|
{
|
etd = (Etd)((DevicePersistenceHistorical)Serialization.deserialize(DevicePersistenceHistorical.class, value)).device;
|
if (etd != null)
|
{
|
if (etd.getDeviceInformation().period != etdPeriod) throw new ServerException(Shared.getMessage(language, "Selected time range has several integration periods"));
|
if (name == null) name = etd.getDeviceInformation().getName();
|
}
|
}
|
|
|
try
|
{
|
EtdStatus status = etd.getDeviceStatus();
|
|
int position = (int)((status.measurementTimestamp - timestamp1)/(aggregationPeriod * 1000));
|
if ((status.measurementTimestamp-timestamp1) < 0)
|
position = -1;
|
|
if ((position >= 0) && (position < numberOfPeriods)) // Podemos tener un registro con timestamp1 < measurementTimestamp por una alarma o algo
|
{
|
if (register == null)
|
{
|
register = new Register(position);
|
}
|
else
|
{
|
if (register.position != position)
|
{
|
register.aggregation();
|
register = new Register(position);
|
}
|
}
|
|
register.mstatus.put(status.measurementTimestamp, status);
|
}
|
}
|
catch (Exception e)
|
{
|
e.printStackTrace();
|
}
|
|
}
|
|
if (etd == null) throw new ServerException("No data available in selected time range");
|
if (register != null) register.aggregation();
|
EtdStatusAggregation response = new EtdStatusAggregation();
|
response.device = identifier;
|
response.name = name;
|
response.section = (section >= 0);
|
if (response.section == true)
|
response.number = section;
|
else
|
response.number = lane;
|
response.timestamp1 = timestamp1;
|
response.timestamp2 = timestamp2;
|
response.aggregationPeriod = aggregationPeriod;
|
|
for (EtdStatus status : lEtdStatus)
|
{
|
EtdStatusAggregationLane data = new EtdStatusAggregationLane();
|
data.timestamp = status.measurementTimestamp;
|
if (lane >=0) data.lane = status.getLane(lane); else data.lane = status.getSection(section);
|
response.ldata.add(data);
|
}
|
|
for (int i=0; i<response.ldata.size(); i++)
|
{
|
EtdStatusAggregationLane laneAggregation = response.ldata.get(i);
|
if (laneAggregation.lane == null)
|
{
|
laneAggregation.lane = new EtdStatusLane();
|
}
|
else
|
{
|
laneAggregation.lane.speed = Math.rint(laneAggregation.lane.speed);
|
}
|
}
|
return response;
|
|
}
|
catch (ServerException exception)
|
{
|
exception.printStackTrace();
|
throw exception;
|
}
|
catch (Exception exception)
|
{
|
exception.printStackTrace();
|
throw new ServerException(exception);
|
}
|
finally
|
{
|
try { result.close(); } catch (Exception e) {};
|
}
|
|
}
|
|
|
|
|
|
private void initialise() throws ServerException, Exception
|
{
|
etdPeriod = etd.getDeviceInformation().period;
|
|
if (aggregationPeriod == 0) aggregationPeriod = etdPeriod;
|
|
if ((aggregationPeriod % etdPeriod) != 0)
|
{
|
throw new ServerException(Shared.getMessage(language, "Selected period must be multiple of traffic counter period"));
|
}
|
|
if (timestamp1 > timestamp2)
|
{
|
throw new ServerException(Shared.getMessage(language, "From timestamp must be lower than to timestamp"));
|
}
|
|
timestamp1 = timestamp1 - (timestamp1 % (aggregationPeriod * 1000));
|
timestamp2 = timestamp2 - (timestamp2 % (aggregationPeriod * 1000));
|
numberOfPeriods = (int)((timestamp2 - timestamp1)/(aggregationPeriod * 1000));
|
if (numberOfPeriods > 133920) throw new ServerException(Shared.getMessage(language, "Result would produce too much registers. Select lower date range or higher period"));
|
|
lEtdStatus = new EtdStatus[numberOfPeriods];
|
long timestamp = timestamp1;
|
for (int i=0; i<numberOfPeriods; i++)
|
{
|
lEtdStatus[i] = new EtdStatus();
|
lEtdStatus[i].measurementTimestamp = timestamp;
|
lEtdStatus[i].status = DeviceStatus.STATUS_NULL;
|
lEtdStatus[i].period = aggregationPeriod;
|
timestamp = timestamp + (aggregationPeriod * 1000);
|
}
|
}
|
|
|
|
|
|
private class Register
|
{
|
public HashMap<Long, EtdStatus> mstatus = new HashMap<Long, EtdStatus>();
|
public int position;
|
|
public Register(int position)
|
{
|
this.position = position;
|
}
|
|
|
public void aggregation()
|
{
|
int totalMeasurements = aggregationPeriod / etd.getDeviceInformation().period;
|
int correctMeasurements = 0;
|
ArrayList<EtdStatus> lstatus = new ArrayList<EtdStatus>(mstatus.values());
|
|
EtdStatus etdStatus = lstatus.get(0);
|
|
// Lanes
|
|
for (int i=0; i<etdStatus.llane.size(); i++)
|
{
|
int totalMeasurementsLane = etdStatus.llane.get(i).totalMeasurements;
|
int correctMeasurementsLane = etdStatus.llane.get(i).correctMeasurements;
|
int apuntes =0 ;
|
|
for (int j=1; j<lstatus.size(); j++)
|
{
|
try
|
{
|
totalMeasurementsLane += lstatus.get(j).llane.get(i).totalMeasurements;
|
correctMeasurementsLane += lstatus.get(j).llane.get(i).correctMeasurements;
|
// totalMeasurementsLane += lstatus.get(j).llane.get(i).totalMeasurements;
|
// totalMeasurementsLane = totalMeasurements;
|
// correctMeasurementsLane += lstatus.get(j).llane.get(i).correctMeasurements;
|
// correctMeasurementsLane = lstatus.get(j).llane.get(i).correctMeasurements;
|
|
if (lstatus.get(j).llane.get(i).correctMeasurements > 0)
|
{
|
apuntes = apuntes + 1;
|
etdStatus.llane.get(i).counting += lstatus.get(j).llane.get(i).counting;
|
etdStatus.llane.get(i).unclassified += lstatus.get(j).llane.get(i).unclassified;
|
etdStatus.llane.get(i).speed += (lstatus.get(j).llane.get(i).counting) * (lstatus.get(j).llane.get(i).speed);
|
etdStatus.llane.get(i).occupancy += (lstatus.get(j).llane.get(i).counting) * (lstatus.get(j).llane.get(i).occupancy);
|
|
for (int k=0; k<etdStatus.llane.get(i).lengths.length; k++)
|
{
|
etdStatus.llane.get(i).lengths[k] += lstatus.get(j).llane.get(i).lengths[k];
|
}
|
|
for (int k=0; k<etdStatus.llane.get(i).speeds.length; k++)
|
{
|
etdStatus.llane.get(i).speeds[k] += lstatus.get(j).llane.get(i).speeds[k];
|
}
|
|
for (int k=0; k<etdStatus.llane.get(i).speedxlength.length; k++)
|
{
|
for (int l=0; l<etdStatus.llane.get(i).speedxlength[k].length; l++)
|
{
|
etdStatus.llane.get(i).speedxlength[k][l] += lstatus.get(j).llane.get(i).speedxlength[k][l];
|
}
|
}
|
}
|
}
|
catch (Exception e)
|
{
|
}
|
}
|
|
|
// totalMeasurements += totalMeasurementsLane;
|
correctMeasurements = Math.max(correctMeasurements, correctMeasurementsLane);
|
|
if (apuntes > 0)
|
{
|
if (etdStatus.llane.get(i).counting > 0)
|
{
|
// etdStatus.llane.get(i).speed /= apuntes;
|
// etdStatus.llane.get(i).occupancy /= apuntes;
|
etdStatus.llane.get(i).speed /= etdStatus.llane.get(i).counting;
|
etdStatus.llane.get(i).occupancy /= etdStatus.llane.get(i).counting;
|
}
|
|
etdStatus.llane.get(i).speed = (int)(etdStatus.llane.get(i).speed);
|
int occupancy = (int)(etdStatus.llane.get(i).occupancy*10);
|
etdStatus.llane.get(i).occupancy = (float)((float)occupancy / 10f);
|
}
|
|
int length = (int)(etdStatus.llane.get(i).length*10);
|
etdStatus.llane.get(i).length = (double)((double)length / 10d);
|
int distance = (int)(etdStatus.llane.get(i).distance*10);
|
etdStatus.llane.get(i).distance = (double)((double)distance / 10d);
|
|
// Write status lane
|
|
try
|
{
|
EtdStatusLane statusLane = etdStatus.llane.get(i);
|
statusLane.correctMeasurements = correctMeasurementsLane;
|
statusLane.totalMeasurements = totalMeasurementsLane;
|
lEtdStatus[position].llane.add(statusLane);
|
}
|
catch (Exception e)
|
{
|
}
|
}
|
|
|
|
|
// Sections
|
|
for (int i=0; i<etdStatus.lsection.size(); i++)
|
{
|
// int totalMeasurementsSection = etdStatus.lsection.get(i).totalMeasurements;
|
int totalMeasurementsSection = etdStatus.lsection.get(i).totalMeasurements;
|
int correctMeasurementsSection = etdStatus.lsection.get(i).correctMeasurements;
|
int apuntes = 0;
|
|
for (int j=1; j<lstatus.size(); j++)
|
{
|
try
|
{
|
totalMeasurementsSection += lstatus.get(j).lsection.get(i).totalMeasurements;
|
correctMeasurementsSection += lstatus.get(j).lsection.get(i).correctMeasurements;
|
|
if (lstatus.get(j).lsection.get(i).correctMeasurements > 0)
|
{
|
apuntes = apuntes + 1;
|
etdStatus.lsection.get(i).counting += lstatus.get(j).lsection.get(i).counting;
|
etdStatus.lsection.get(i).unclassified += lstatus.get(j).lsection.get(i).unclassified;
|
etdStatus.lsection.get(i).speed += (lstatus.get(j).lsection.get(i).counting) * (lstatus.get(j).lsection.get(i).speed);
|
etdStatus.lsection.get(i).occupancy += (lstatus.get(j).lsection.get(i).counting) * (lstatus.get(j).lsection.get(i).occupancy);
|
|
for (int k=0; k<etdStatus.lsection.get(i).lengths.length; k++)
|
{
|
etdStatus.lsection.get(i).lengths[k] += lstatus.get(j).lsection.get(i).lengths[k];
|
}
|
|
for (int k=0; k<etdStatus.lsection.get(i).speeds.length; k++)
|
{
|
etdStatus.lsection.get(i).speeds[k] += lstatus.get(j).lsection.get(i).speeds[k];
|
}
|
|
for (int k=0; k<etdStatus.lsection.get(i).speedxlength.length; k++)
|
{
|
for (int l=0; l<etdStatus.lsection.get(i).speedxlength[k].length; l++)
|
{
|
etdStatus.lsection.get(i).speedxlength[k][l] += lstatus.get(j).lsection.get(i).speedxlength[k][l];
|
}
|
}
|
}
|
}
|
catch (Exception e)
|
{
|
}
|
}
|
|
|
// totalMeasurements += totalMeasurementsSection;
|
correctMeasurements += correctMeasurementsSection;
|
|
if (apuntes > 0)
|
{
|
if (etdStatus.lsection.get(i).counting > 0)
|
{
|
etdStatus.lsection.get(i).speed /= etdStatus.lsection.get(i).counting;
|
etdStatus.lsection.get(i).occupancy /= etdStatus.lsection.get(i).counting;
|
}
|
|
etdStatus.lsection.get(i).speed = (int)(etdStatus.lsection.get(i).speed);
|
int occupancy = (int)(etdStatus.lsection.get(i).occupancy*10);
|
etdStatus.lsection.get(i).occupancy = (float)((float)occupancy / 10f);
|
}
|
|
int length = (int)(etdStatus.lsection.get(i).length*10);
|
etdStatus.lsection.get(i).length = (double)((double)length / 10d);
|
int distance = (int)(etdStatus.lsection.get(i).distance*10);
|
etdStatus.lsection.get(i).distance = (double)((double)distance / 10d);
|
|
// Write status section
|
|
try
|
{
|
EtdStatusLane statusSection = etdStatus.lsection.get(i);
|
statusSection.correctMeasurements = correctMeasurementsSection;
|
statusSection.totalMeasurements = totalMeasurementsSection;
|
lEtdStatus[position].lsection.add(statusSection);
|
}
|
catch (Exception e)
|
{
|
}
|
}
|
|
|
// Totals
|
|
{
|
|
int apuntes = 0;
|
|
for (int j=1; j<lstatus.size(); j++)
|
{
|
try
|
{
|
etdStatus.total.totalMeasurements += lstatus.get(j).total.totalMeasurements;
|
etdStatus.total.correctMeasurements += lstatus.get(j).total.correctMeasurements;
|
|
if (lstatus.get(j).total.correctMeasurements > 0)
|
{
|
apuntes = apuntes + 1;
|
etdStatus.total.counting += lstatus.get(j).total.counting;
|
etdStatus.total.unclassified += lstatus.get(j).total.unclassified;
|
etdStatus.total.speed += (lstatus.get(j).total.counting) * (lstatus.get(j).total.speed);
|
etdStatus.total.occupancy += (lstatus.get(j).total.counting) * (lstatus.get(j).total.occupancy);
|
|
for (int k=0; k<etdStatus.total.lengths.length; k++)
|
{
|
etdStatus.total.lengths[k] += lstatus.get(j).total.lengths[k];
|
}
|
|
for (int k=0; k<etdStatus.total.speeds.length; k++)
|
{
|
etdStatus.total.speeds[k] += lstatus.get(j).total.speeds[k];
|
}
|
|
for (int k=0; k<etdStatus.total.speedxlength.length; k++)
|
{
|
for (int l=0; l<etdStatus.total.speedxlength[k].length; l++)
|
{
|
etdStatus.total.speedxlength[k][l] += lstatus.get(j).total.speedxlength[k][l];
|
}
|
}
|
}
|
}
|
catch (Exception e)
|
{
|
}
|
}
|
|
|
// Write totals
|
|
if (etdStatus.total != null)
|
{
|
if (apuntes > 0)
|
{
|
if (etdStatus.total.counting > 0)
|
{
|
etdStatus.total.speed /= etdStatus.total.counting;
|
etdStatus.total.occupancy /= etdStatus.total.counting;
|
}
|
|
etdStatus.total.speed = (int)etdStatus.total.speed;
|
int occupancy = (int)(etdStatus.total.occupancy*10);
|
etdStatus.total.occupancy = (float)((float)occupancy / 10f);
|
}
|
|
int length = (int)(etdStatus.total.length*10);
|
etdStatus.total.length = (double)((double)length / 10d);
|
int distance = (int)(etdStatus.total.distance*10);
|
etdStatus.total.distance = (double)((double)distance / 10d);
|
|
try
|
{
|
lEtdStatus[position].total = etdStatus.total;
|
}
|
catch (Exception e)
|
{
|
}
|
}
|
}
|
|
}
|
}
|
|
}
|