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 ldevice = (List)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 ldevice = (List)DevicePersistenceTimeless.getDevices((List)(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() { 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() { 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) { } } }