package art.servers.fleetserver;
|
|
import art.library.interop.serialization.Serialization;
|
import art.library.model.devices.Device;
|
import art.library.model.devices.DeviceInformation;
|
import art.library.model.devices.DevicePersistenceHistorical;
|
import art.library.model.devices.DevicePersistenceTimeless;
|
import art.library.model.devices.vehicle.Vehicle;
|
import art.library.model.devices.vehicle.VehicleInformation;
|
import art.library.model.devices.vehicle.VehiclePosition;
|
import art.library.model.devices.vehicle.status.VehicleStatusBusPriority;
|
import art.library.osm.OSM;
|
import art.servers.configuration.Configuration;
|
import java.io.File;
|
import java.io.FileOutputStream;
|
import java.lang.reflect.Array;
|
import java.lang.reflect.Constructor;
|
import java.text.SimpleDateFormat;
|
import java.util.Calendar;
|
import java.util.Collections;
|
import java.util.Comparator;
|
import java.util.List;
|
|
public class Model extends art.servers.Model
|
{
|
|
public Model(Configuration configuration) throws Exception
|
{
|
super(configuration, "vehicles", Vehicle.class.getName(), VehicleInformation.class.getName());
|
}
|
|
|
public void readDevices()
|
{
|
if (filename == null) return;
|
|
mutexListDevices.lockWrite();
|
|
try
|
{
|
|
ldevice.clear();
|
mdevice.clear();
|
|
// Read data from database file (--restore)
|
|
if (art.servers.Shared.restoreDevices == true)
|
{
|
Class clazzDevice = Class.forName(deviceClassName);
|
Class<?> clazzArray = (Class<?>)Array.newInstance(clazzDevice, 0).getClass();
|
List<Device> ldevice = (List<Device>)Serialization.deserialize(clazzArray, new File(art.servers.Shared.getApplicationName() + "." + filename + ".database.json"));
|
|
for (Device device : ldevice)
|
{
|
if ((device instanceof Device) && (device.information.serverPort == art.servers.Shared.configuration.listener.port) && (device.information.serverAddress.equalsIgnoreCase(art.servers.Shared.configuration.listener.address)))
|
{
|
device.information.serverAddress = art.servers.Shared.configuration.listener.address;
|
device.information.serverPort = art.servers.Shared.configuration.listener.port;
|
device.information.serverAddressExternal = art.servers.Shared.configuration.listener.addressExternal;
|
device.information.serverPortExternal = art.servers.Shared.configuration.listener.portExternal;
|
this.ldevice.add(device);
|
this.mdevice.put(device.getIdentifier(), device);
|
}
|
}
|
}
|
|
// Read data from database
|
|
else if ((art.servers.Shared.controllerDatabase != null) && (art.servers.Shared.reloadDevices == false))
|
{
|
Class clazzDevice = Class.forName(deviceClassName);
|
|
List<Device> ldevice = (List<Device>)DevicePersistenceTimeless.getDevices((List<Object>)(List<?>)art.servers.Shared.controllerDatabase.timeless_getObject(DevicePersistenceTimeless.class.getName(), "type = '" + clazzDevice.getName() + "'"));
|
System.out.println( "Devices bbdd: " + ldevice.size());
|
for (Device device : ldevice)
|
{
|
if ((device instanceof Device) && (device.information.serverPort == art.servers.Shared.configuration.listener.port) && (device.information.serverAddress.equalsIgnoreCase(art.servers.Shared.configuration.listener.address)))
|
{
|
device.information.serverAddress = art.servers.Shared.configuration.listener.address;
|
device.information.serverPort = art.servers.Shared.configuration.listener.port;
|
device.information.serverAddressExternal = art.servers.Shared.configuration.listener.addressExternal;
|
device.information.serverPortExternal = art.servers.Shared.configuration.listener.portExternal;
|
this.ldevice.add(device);
|
this.mdevice.put(device.getIdentifier(), device);
|
}
|
}
|
System.out.println( "Devices bbdd model: " + this.ldevice.size());
|
}
|
|
}
|
catch (Exception exception)
|
{
|
art.servers.Shared.println(art.servers.Shared.getMessage("Model"), exception);
|
}
|
|
|
|
|
try
|
{
|
Class clazzDevice = Class.forName(deviceClassName);
|
Class clazzInformation = Class.forName(deviceInformationClassName);
|
|
DeviceInformation[] ldeviceInformation = null;
|
|
if (new File(art.servers.Shared.getApplicationName() + "." + filename + ".json").exists())
|
{
|
System.out.println( "Devices file exists.1: " + this.ldevice.size());
|
Class<?> clazzArray = (Class<?>)Array.newInstance(clazzInformation, 0).getClass();
|
ldeviceInformation = Serialization.deserialize(clazzArray, new File(art.servers.Shared.getApplicationName() + "." + filename + ".json"));
|
System.out.println( "Devices file exists.2: " + ldeviceInformation.length);
|
}
|
else
|
{
|
System.out.println( "Devices file not exists: " + art.servers.Shared.getApplicationName() + "." + filename + ".json");
|
}
|
|
int i = 0;
|
for (DeviceInformation deviceInformation : ldeviceInformation)
|
{
|
if (mdevice.containsKey(deviceInformation.getIdentifier()) == false)
|
{
|
System.out.println("Adding device: " + i + " - " + ((VehicleInformation)deviceInformation).ISSI);
|
addDevice(clazzDevice, deviceInformation);
|
System.out.println("Added device: " + i);
|
i++;
|
}
|
}
|
|
System.out.println( "Devices file : " + this.ldevice.size());
|
}
|
catch (Exception exception)
|
{
|
exception.printStackTrace();
|
art.servers.Shared.println(art.servers.Shared.getMessage("Model"), exception);
|
}
|
|
|
|
for (Device device : ldevice)
|
{
|
device.information.serverServiceName = art.servers.Shared.controllerStatus.getApplication().getDeviceInformation().serverServiceName;
|
}
|
|
|
// Sort
|
|
Collections.sort(ldevice, new Comparator<Device>()
|
{
|
public int compare(Device device1, Device device2)
|
{
|
return Integer.valueOf(device1.information.number).compareTo(device2.information.number);
|
}
|
});
|
|
|
// Database file
|
|
if (art.servers.Shared.restoreDevices == false)
|
{
|
try
|
{
|
|
FileOutputStream fos = new FileOutputStream(new File(art.servers.Shared.getApplicationName() + "." + filename + ".database.json"));
|
|
fos.write("[\n".getBytes());
|
|
for (Device device : ldevice)
|
{
|
fos.write(Serialization.toPrettyString(device).getBytes());
|
if (device != ldevice.get(ldevice.size() - 1)) fos.write(",".getBytes());
|
}
|
|
fos.write("]\n".getBytes());
|
fos.close();
|
}
|
catch (Exception e)
|
{
|
}
|
}
|
|
|
mutexListDevices.releaseWrite();
|
|
}
|
|
|
|
|
|
|
private void addDevice(Class clazzDevice, DeviceInformation information) throws Exception
|
{
|
Device device = mdevice.get(information.getIdentifier());
|
|
long timestamp = System.currentTimeMillis();
|
|
if (device == null)
|
{
|
Constructor<?> constructor = clazzDevice.getConstructor(String.class);
|
Object object = constructor.newInstance(new Object[]{information.getIdentifier()});
|
device = (Device)object;
|
device.information = information;
|
device.information.setCreationTimestamp(timestamp);
|
device.information.serverAddress = art.servers.Shared.configuration.listener.address;
|
device.information.serverPort = art.servers.Shared.configuration.listener.port;
|
device.information.serverAddressExternal = art.servers.Shared.configuration.listener.addressExternal;
|
device.information.serverPortExternal = art.servers.Shared.configuration.listener.portExternal;
|
device.setLastTimestampInformationUpdate(timestamp);
|
if (art.servers.Shared.controllerDatabase != null)
|
{
|
art.servers.Shared.controllerDatabase.timeless_updateOrAddObject(new DevicePersistenceTimeless(device));
|
|
DevicePersistenceHistorical deviceHistorical = new DevicePersistenceHistorical(device);
|
|
try
|
{
|
art.servers.Shared.controllerDatabase.historical_addOrUpdateObject(deviceHistorical);
|
}
|
catch (org.postgresql.util.PSQLException exception)
|
{
|
if ((exception.getMessage().toUpperCase().indexOf("NO PARTITION OF RELATION") > -1) ||
|
(exception.getMessage().toUpperCase().indexOf("NO SE ENCONTRÓ UNA PARTICIÓN") > -1))
|
{
|
Calendar calendar1 = Calendar.getInstance();
|
calendar1.setTimeInMillis(device.getLastTimestampUpdate());
|
calendar1.set(Calendar.DATE, 1);
|
calendar1.set(Calendar.HOUR_OF_DAY, 0);
|
calendar1.set(Calendar.MINUTE, 0);
|
calendar1.set(Calendar.SECOND, 0);
|
calendar1.set(Calendar.MILLISECOND, 0);
|
|
SimpleDateFormat formato1 = new SimpleDateFormat("yyyy_MM");
|
|
String tablename = "devices_" + formato1.format(calendar1.getTimeInMillis());
|
long startdate = calendar1.getTimeInMillis();
|
calendar1.add(Calendar.MONTH, 1);
|
long enddate = calendar1.getTimeInMillis();
|
|
String query1 = "CREATE TABLE IF NOT EXISTS " + tablename + " PARTITION OF devices FOR VALUES FROM ('" + startdate + "') TO ('" + enddate + "')";
|
try{art.servers.Shared.controllerDatabase.historical_update(query1);} catch (Exception e){};
|
executeAlterTableDevicesVacuum(true, tablename);
|
|
// Do again the insert
|
try
|
{
|
art.servers.Shared.controllerDatabase.historical_addOrUpdateObject(deviceHistorical);
|
}
|
catch (Exception e)
|
{
|
art.servers.Shared.println(art.servers.Shared.getMessage("Model"), e);
|
}
|
}
|
}
|
}
|
|
mdevice.put(device.getIdentifier(), device);
|
ldevice.add(device);
|
}
|
else
|
{
|
if (Serialization.equals(device.information, information) == false)
|
{
|
device.information = information;
|
device.setLastTimestampInformationUpdate(timestamp);
|
art.servers.Shared.controllerDatabase.timeless_updateOrAddObject(new DevicePersistenceTimeless(device));
|
|
try
|
{
|
art.servers.Shared.controllerDatabase.historical_addOrUpdateObject(new DevicePersistenceHistorical(device));
|
}
|
catch (org.postgresql.util.PSQLException exception)
|
{
|
if ((exception.getMessage().toUpperCase().indexOf("NO PARTITION OF RELATION") > -1) ||
|
(exception.getMessage().toUpperCase().indexOf("NO SE ENCONTRÓ UNA PARTICIÓN") > -1))
|
{
|
Calendar calendar1 = Calendar.getInstance();
|
calendar1.setTimeInMillis(device.getLastTimestampUpdate());
|
calendar1.set(Calendar.DATE, 1);
|
calendar1.set(Calendar.HOUR_OF_DAY, 0);
|
calendar1.set(Calendar.MINUTE, 0);
|
calendar1.set(Calendar.SECOND, 0);
|
calendar1.set(Calendar.MILLISECOND, 0);
|
|
SimpleDateFormat formato1 = new SimpleDateFormat("yyyy_MM");
|
|
String tablename = "devices_" + formato1.format(calendar1.getTimeInMillis());
|
long startdate = calendar1.getTimeInMillis();
|
calendar1.add(Calendar.MONTH, 1);
|
long enddate = calendar1.getTimeInMillis();
|
|
String query1 = "CREATE TABLE IF NOT EXISTS " + tablename + " PARTITION OF devices FOR VALUES FROM ('" + startdate + "') TO ('" + enddate + "')";
|
try{art.servers.Shared.controllerDatabase.historical_update(query1);} catch (Exception e){};
|
executeAlterTableDevicesVacuum(true, tablename);
|
|
// Do again the insert
|
try
|
{
|
art.servers.Shared.controllerDatabase.historical_addOrUpdateObject(new DevicePersistenceHistorical(device));
|
}
|
catch (Exception e)
|
{
|
art.servers.Shared.println(art.servers.Shared.getMessage("Model"), e);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
public void addDevices(DeviceInformation[] linformation) throws Exception
|
{
|
// Es ineficiente, pero hay que tener en cuenta que es una operación residual
|
|
mutexListDevices.lockWrite();
|
|
try
|
{
|
for (DeviceInformation information : linformation)
|
{
|
addDevice(Class.forName(this.deviceClassName), information);
|
}
|
|
Collections.sort(ldevice, new Comparator<Device>()
|
{
|
public int compare(Device device1, Device device2)
|
{
|
return Integer.valueOf(device1.information.number).compareTo(device2.information.number);
|
}
|
});
|
|
}
|
finally
|
{
|
mutexListDevices.releaseWrite();
|
}
|
}
|
|
|
public void updateDevice(Vehicle vehiclecurrent, VehiclePosition currentPosition, VehicleStatusBusPriority busPriority)
|
{
|
Vehicle vehicleclone = Serialization.clone(vehiclecurrent);
|
VehiclePosition previousPosition = vehicleclone.getDeviceStatus().position;
|
|
try
|
{
|
if ((Shared.logBus == true) && (busPriority != null))
|
{
|
Shared.println("UpdateDevice",Device.getDate(System.currentTimeMillis())+";BusPriority="+Device.getDate(busPriority.timestamp)+";"+busPriority.lightcontroller+";"+busPriority.latitude+";"+busPriority.longitude+";"+busPriority.direction+";"+busPriority.speed+";Demand="+busPriority.demand+";Operation="+busPriority.operation+";Green="+busPriority.greenTime);
|
}
|
|
if (previousPosition != null)
|
{
|
if (previousPosition.timestamp > 0)
|
{
|
currentPosition.direction = (float)(Math.atan2((currentPosition.longitude - previousPosition.longitude), (currentPosition.latitude - previousPosition.latitude)) * 180 / Math.PI);
|
double distance = OSM.mercator.getDistance(previousPosition.latitude, previousPosition.longitude, currentPosition.latitude, currentPosition.longitude);
|
currentPosition.speed = (float)((distance / ((currentPosition.timestamp - previousPosition.timestamp) / 1000.0)) * 3.6);
|
|
if (distance < Math.max(previousPosition.accuracy, currentPosition.accuracy))
|
{
|
currentPosition.speed = 0;
|
}
|
|
currentPosition.timeElapsed = (currentPosition.timestamp - previousPosition.timestamp)/1000;
|
}
|
}
|
|
vehicleclone.getDeviceStatus().position = currentPosition;
|
vehicleclone.getDeviceInformation().latitude = 0;
|
vehicleclone.getDeviceInformation().longitude = 0;
|
vehicleclone.setLastTimestampStatusUpdate(currentPosition.timestamp);
|
vehicleclone.setAlarm("alarm_offline", 0);
|
vehicleclone.setAlarm("alarm_invalid", 0);
|
|
VehicleStatusBusPriority currentBusPriority = vehicleclone.getDeviceStatus().busPriority;
|
|
if ((currentBusPriority != null) && (busPriority == null))
|
{
|
art.servers.fleetserver.configuration.Configuration configuration = (art.servers.fleetserver.configuration.Configuration)Shared.configuration;
|
|
if ((System.currentTimeMillis() - currentBusPriority.timestamp) > (configuration.detail.timeToRemoveBusPriority*1000L))
|
{
|
vehicleclone.getDeviceStatus().busPriority = null;
|
if ((Shared.logBus == true) && (busPriority == null))
|
{
|
System.out.println( Device.getDate(System.currentTimeMillis())+";"+vehicleclone.getIdentifier()+";BusPriorityToNull;"+Device.getDate(currentBusPriority.timestamp)+";"+configuration.detail.timeToRemoveBusPriority);
|
Shared.println("UpdateDevice",Device.getDate(System.currentTimeMillis())+";"+vehicleclone.getIdentifier()+";BusPriorityToNull;"+Device.getDate(currentBusPriority.timestamp)+";"+configuration.detail.timeToRemoveBusPriority);
|
}
|
}
|
}
|
else
|
{
|
vehicleclone.getDeviceStatus().busPriority = busPriority;
|
if ((Shared.logBus == true) && (busPriority != null))
|
{
|
Shared.println("UpdateDevice",Device.getDate(System.currentTimeMillis())+";"+vehicleclone.getIdentifier()+";BusPriorityStatus="+Device.getDate(vehicleclone.getDeviceStatus().busPriority.timestamp)+";"+vehicleclone.getDeviceStatus().busPriority.lightcontroller+";"+vehicleclone.getDeviceStatus().busPriority.latitude+";"+vehicleclone.getDeviceStatus().busPriority.longitude+";"+vehicleclone.getDeviceStatus().busPriority.direction+";"+vehicleclone.getDeviceStatus().busPriority.speed+";Demand="+vehicleclone.getDeviceStatus().busPriority.demand+";Operation="+vehicleclone.getDeviceStatus().busPriority.operation+";Green="+vehicleclone.getDeviceStatus().busPriority.greenTime);
|
}
|
}
|
|
Shared.model.updateDevice(vehiclecurrent, vehicleclone);
|
}
|
catch (Exception e)
|
{
|
}
|
}
|
|
|
|
}
|