package art.servers.etdserver.controller;
|
|
|
import art.library.model.devices.DeviceStatus;
|
import art.library.model.devices.etd.Etd;
|
import art.library.model.devices.etd.EtdInformation;
|
import art.library.interop.serialization.Serialization;
|
import art.library.model.devices.Device;
|
import art.library.model.devices.etd.status.EtdStatusVehicle;
|
import art.library.model.transactions.traces.Trace;
|
import art.library.utils.synchro.Mutex;
|
import art.servers.ServerException;
|
import art.servers.etdserver.Shared;
|
import art.servers.etdserver.protocols.diamond.Diamond_Message;
|
import art.servers.etdserver.protocols.diamond.Diamond_ProtocolAnalyser;
|
import art.servers.etdserver.protocols.diamond.Diamond_ProtocolConstructor;
|
import java.io.File;
|
import java.io.FileOutputStream;
|
import java.io.InputStream;
|
import java.io.OutputStream;
|
import static java.lang.Thread.sleep;
|
import java.net.Socket;
|
import java.net.SocketTimeoutException;
|
import java.text.SimpleDateFormat;
|
import java.util.ArrayList;
|
import java.util.Calendar;
|
import java.util.Date;
|
import java.util.List;
|
|
|
public class ControllerDiamondRaw extends ControllerEtd
|
{
|
private SimpleDateFormat sdh = new SimpleDateFormat("HH:mm");
|
private boolean connected = false;
|
private Socket socket = null;
|
private InputStream is = null;
|
private OutputStream os = null;
|
private int status = DeviceStatus.STATUS_ALARM;
|
private boolean firstTime = true;
|
private long lastVehicle = System.currentTimeMillis();
|
private long MAX_TIME_WITHOUT_VEHICLE_DETECTION = 30L*60000L;
|
private int MAX_VEHICLES = 100;
|
private Mutex mutexList = new Mutex();
|
private List<EtdStatusVehicle> lvehicle = new ArrayList<EtdStatusVehicle>();
|
private ControllerDataIntegration controllerDataIntegration = null;
|
private long diftime = 0;
|
|
|
public ControllerDiamondRaw(Etd etd)
|
{
|
super(etd);
|
this.device = etd;
|
this.name = Shared.getMessage("Controller etd") + " " + etd.information.name;
|
}
|
|
|
|
|
public void run()
|
{
|
controllerDataIntegration = new ControllerDataIntegration((ControllerEtd)this);
|
controllerDataIntegration.start();
|
// <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)
|
{
|
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>
|
}
|
|
|
|
|
/*
|
Private controller functions
|
*/
|
|
private void update() throws Exception
|
{
|
Etd etdclone = (Etd)Serialization.clone(device);
|
|
try
|
{
|
EtdInformation etdInformation = (EtdInformation)etdclone.getDeviceInformation();
|
|
startMonitorTrafficData(etdclone);
|
|
// TODO
|
// How to maintain traffic counter in time?
|
|
while (true)
|
{
|
try
|
{
|
// Have a timeout, which if exceeded close connection and re-activate monitoring
|
// EtdRealtime realtime = (EtdRealtime)etd.getDeviceRealtime();
|
|
Diamond_Message response = read(new byte[0]);
|
List<EtdStatusVehicle> list = Diamond_ProtocolAnalyser.analyseVehicleResponse(etdclone, response.getResponseString());
|
if (list.size() > 0) lastVehicle = System.currentTimeMillis();
|
if (list.size() == 1)
|
{
|
EtdStatusVehicle vehicle = list.get(0);
|
diftime = System.currentTimeMillis()-vehicle.timestamp;
|
}
|
|
try
|
{
|
for (EtdStatusVehicle vehicle : list)
|
{
|
mutexList.lockWrite(5000);
|
|
try
|
{
|
vehicle.timestamp = vehicle.timestamp + diftime;
|
logVehicle(etdclone, vehicle);
|
lvehicle.add(vehicle);
|
checkListSize();
|
}
|
catch (Exception e)
|
{
|
|
}
|
|
mutexList.releaseWrite();
|
}
|
}
|
catch (Exception e)
|
{
|
|
}
|
|
|
if ((System.currentTimeMillis()-lastVehicle) > MAX_TIME_WITHOUT_VEHICLE_DETECTION)
|
{
|
lastVehicle = System.currentTimeMillis();
|
try{disconnect();} catch (Exception ex){};
|
return;
|
}
|
}
|
catch (SocketTimeoutException e)
|
{
|
if ((System.currentTimeMillis()-lastVehicle) > MAX_TIME_WITHOUT_VEHICLE_DETECTION)
|
{
|
e.printStackTrace();
|
lastVehicle = System.currentTimeMillis();
|
try{disconnect();} catch (Exception ex){};
|
return;
|
}
|
}
|
catch (ServerException e)
|
{
|
e.printStackTrace();
|
throw e;
|
}
|
catch (Exception e)
|
{
|
e.printStackTrace();
|
throw e;
|
}
|
}
|
}
|
catch (Exception 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);
|
}
|
|
try{disconnect();} catch (Exception ex){};
|
}
|
}
|
|
|
public List<EtdStatusVehicle> getVehicles (long timestamp)
|
{
|
List<EtdStatusVehicle> lresult = new ArrayList<EtdStatusVehicle>();
|
|
try
|
{
|
mutexList.lockRead();
|
|
for (EtdStatusVehicle vehicle : lvehicle)
|
{
|
if (vehicle.timestamp > timestamp)
|
{
|
lresult.add(vehicle);
|
}
|
}
|
|
return(lresult);
|
}
|
catch (Exception e)
|
{
|
}
|
finally
|
{
|
mutexList.releaseRead();
|
}
|
|
return(lresult);
|
}
|
|
|
public List<EtdStatusVehicle> getVehiclesPeriod (long timestamp1, long timestamp2)
|
{
|
List<EtdStatusVehicle> lresult = new ArrayList<EtdStatusVehicle>();
|
|
try
|
{
|
mutexList.lockRead();
|
|
for (EtdStatusVehicle vehicle : lvehicle)
|
{
|
if ((vehicle.timestamp >= timestamp1) && (vehicle.timestamp <= timestamp2))
|
{
|
lresult.add(vehicle);
|
}
|
}
|
|
return(lresult);
|
}
|
catch (Exception e)
|
{
|
}
|
finally
|
{
|
mutexList.releaseRead();
|
}
|
|
return(lresult);
|
}
|
|
|
|
|
private void startMonitorTrafficData (Etd etdclone) throws Exception
|
{
|
try
|
{
|
byte[] command = Diamond_ProtocolConstructor.CR();
|
Diamond_Message response = read(command);
|
response.checkError();
|
}
|
catch (Exception e)
|
{
|
|
}
|
|
try
|
{
|
byte[] command = Diamond_ProtocolConstructor.RESETCOMMS();
|
Diamond_Message response = read(command);
|
response.checkError();
|
}
|
catch (Exception e)
|
{
|
|
}
|
|
int retries = 0;
|
while (retries < 5)
|
{
|
try
|
{
|
byte[] command = Diamond_ProtocolConstructor.CR();
|
Diamond_Message response = read(command);
|
response.checkError();
|
|
if ((response.getResponseString().toUpperCase().indexOf("PHO") > -1) ||
|
(response.getResponseString().toUpperCase().indexOf("UN") > -1))
|
{
|
int index = response.getResponseString().indexOf("PHO#");
|
if (index < 0)
|
{
|
index = response.getResponseString().indexOf("UNI#");
|
}
|
|
if (index > -1)
|
{
|
String sversion = response.getResponseString().substring(index+4, index+7);
|
int version = Integer.parseInt(sversion);
|
float f = (float)(((float)version) / 100f);
|
if ((etdclone.getDeviceInformation().firmwareVersion == null) || (etdclone.getDeviceInformation().firmwareVersion.length() == 0))
|
etdclone.getDeviceInformation().firmwareVersion = "" + f;
|
}
|
|
retries = 5;
|
}
|
}
|
catch (Exception e)
|
{
|
|
}
|
|
retries++;
|
}
|
|
|
// Check datetime before starting monitor traffic data
|
checkDatetime(etdclone);
|
|
boolean error = true;
|
retries = 0;
|
while (error == true)
|
{
|
try
|
{
|
byte[] command = Diamond_ProtocolConstructor.startMonitorTrafficData();
|
Diamond_Message response = read(command);
|
response.checkError();
|
Diamond_ProtocolAnalyser.analyseStartMonitorTrafficDataResponse(response);
|
error = false;
|
}
|
catch (Exception e)
|
{
|
retries++;
|
if (retries == 3) throw e;
|
}
|
}
|
}
|
|
|
private void startCollecting (Etd etdclone)
|
{
|
try
|
{
|
byte[] command = Diamond_ProtocolConstructor.startCollecting();
|
Diamond_Message response = read(command);
|
response.checkError();
|
response.checkCommand(response.getResponseString().getBytes(), command);
|
}
|
catch (Exception e)
|
{
|
|
}
|
}
|
|
|
private void stopCollecting ()
|
{
|
try
|
{
|
byte[] command = Diamond_ProtocolConstructor.stopCollecting();
|
Diamond_Message response = read(command);
|
response.checkError();
|
response.checkCommand(response.getResponseString().getBytes(), command);
|
}
|
catch (Exception e)
|
{
|
|
}
|
}
|
|
|
private void checkDatetime (Etd etdclone)
|
{
|
try
|
{
|
byte[] command = Diamond_ProtocolConstructor.getSystemStatusCounter();
|
Diamond_Message response = read(command);
|
long timestamp = System.currentTimeMillis();
|
response.checkError();
|
response.checkCommand(response.getResponseString().getBytes(), command);
|
|
Diamond_Message message = new Diamond_Message();
|
message.setData(response.getDataByte(), command);
|
long timeDifference = 0;
|
long currenttime = 0;
|
boolean collecting = false;
|
|
if (etdclone.getDeviceInformation().firmwareVersion.indexOf("5.") > -1)
|
{
|
message.get6X();
|
message.get2X();
|
message.get2X();
|
message.get2X();
|
message.get4X();
|
message.get4X();
|
message.get4X();
|
message.get6X();
|
message.get6X();
|
message.get1X();
|
collecting = (message.get1X() == 0x01);
|
int hour = message.get2X();
|
int minute = message.get2X();
|
int seconds = message.get2X();
|
int mseconds = message.get2X();
|
int month = message.get2X();
|
int date = message.get2X();
|
int year = message.get2X();
|
int dayOfWeek = message.get2X();
|
|
Calendar calendar = Calendar.getInstance();
|
calendar.set(Calendar.HOUR_OF_DAY, hour);
|
calendar.set(Calendar.MINUTE, minute);
|
calendar.set(Calendar.SECOND, seconds);
|
calendar.set(Calendar.MILLISECOND, mseconds);
|
calendar.set(Calendar.YEAR, year+2000);
|
calendar.set(Calendar.MONTH, month-1);
|
calendar.set(Calendar.DATE, date);
|
|
currenttime = calendar.getTimeInMillis();
|
timeDifference = Math.abs((currenttime-timestamp));
|
}
|
else
|
{
|
message.get6X();
|
message.get2X();
|
message.get2X();
|
message.get4X();
|
message.get4X();
|
message.get6X();
|
message.get6X();
|
message.get1X();
|
collecting = (message.get1X() == 0x01);
|
int hour = message.get2X();
|
int minute = message.get2X();
|
int seconds = message.get2X();
|
int mseconds = message.get2X();
|
int month = message.get2X();
|
int date = message.get2X();
|
int year = message.get2X();
|
int dayOfWeek = message.get2X();
|
|
Calendar calendar = Calendar.getInstance();
|
calendar.set(Calendar.HOUR_OF_DAY, hour);
|
calendar.set(Calendar.MINUTE, minute);
|
calendar.set(Calendar.SECOND, seconds);
|
calendar.set(Calendar.MILLISECOND, mseconds);
|
calendar.set(Calendar.YEAR, year+2000);
|
calendar.set(Calendar.MONTH, month-1);
|
calendar.set(Calendar.DATE, date);
|
|
currenttime = calendar.getTimeInMillis();
|
timeDifference = Math.abs((currenttime-timestamp));
|
}
|
|
if (timeDifference >= 10000)
|
{
|
Shared.println(device.information.name, "Datetime incorrect: " + new Date(timestamp).toString() + " - " + new Date(currenttime).toString() + " - DIF: " + timeDifference + " - Collecting?: " + collecting);
|
|
if (collecting == true)
|
{
|
// Stop collecting before set datetime
|
stopCollecting();
|
}
|
|
updateDatetimeCounter(etdclone);
|
|
startCollecting(etdclone);
|
}
|
}
|
catch (Exception e)
|
{
|
|
}
|
}
|
|
|
private void updateDatetimeCounter (Etd etdclone)
|
{
|
try
|
{
|
byte[] command = Diamond_ProtocolConstructor.sendDatetimeCounter();
|
Diamond_Message response = read(command);
|
response.checkError();
|
response.checkCommand(response.getResponseString().getBytes(), command);
|
Shared.println(device.information.name, "Datetime updated OK");
|
}
|
catch (Exception e)
|
{
|
e.printStackTrace();
|
Shared.println(device.information.name, e);
|
}
|
}
|
|
|
|
|
private void updateVersion (Etd etdclone, String connectionString)
|
{
|
try
|
{
|
int index = connectionString.indexOf("PHO#");
|
if (index < 0)
|
{
|
index = connectionString.indexOf("UNI#");
|
}
|
|
if (index > -1)
|
{
|
String sversion = connectionString.substring(index+4, index+7);
|
int version = Integer.parseInt(sversion);
|
float f = (float)(((float)version) / 100f);
|
if ((etdclone.getDeviceInformation().firmwareVersion == null) || (etdclone.getDeviceInformation().firmwareVersion.length() == 0))
|
etdclone.getDeviceInformation().firmwareVersion = "" + f;
|
}
|
}
|
catch (Exception e)
|
{
|
|
}
|
}
|
|
|
public boolean isConnected ()
|
{
|
return(this.connected);
|
}
|
|
|
private void connect()
|
{
|
try
|
{
|
if (this.socket != null)
|
{
|
if (this.connected == true)
|
{
|
return;
|
}
|
}
|
|
this.socket = new Socket(this.device.getDeviceInformation().connection.address, this.device.getDeviceInformation().connection.port);
|
this.socket.setSoTimeout(this.device.getDeviceInformation().connection.timeout);
|
this.is = this.socket.getInputStream();
|
this.os = this.socket.getOutputStream();
|
this.connected = true;
|
|
if (status != DeviceStatus.STATUS_ONLINE)
|
{
|
String message = Shared.getMessage("Connected, address = %1, port = %2, timeout = %3");
|
message = message.replace("%1", device.getDeviceInformation().connection.address);
|
message = message.replace("%2", "" +device.getDeviceInformation().connection.port);
|
message = message.replace("%3", "" + device.getDeviceInformation().connection.timeout);
|
Shared.println(device.information.name, message);
|
status = DeviceStatus.STATUS_ONLINE;
|
}
|
|
}
|
catch (Exception e)
|
{
|
try{disconnect();} catch (Exception ex){};
|
}
|
|
}
|
|
|
private void disconnect() throws Exception
|
{
|
try { is.close(); }catch (Exception e) {}
|
try { os.close(); }catch (Exception e) {}
|
try { socket.close(); }catch (Exception e) {}
|
is = null;
|
os = null;
|
socket = null;
|
this.connected = false;
|
}
|
|
|
|
private Diamond_Message read(byte[] command) throws Exception
|
{
|
try
|
{
|
if (command.length > 0) send(command);
|
return receive();
|
}
|
catch (Exception e)
|
{
|
throw e;
|
}
|
}
|
|
|
|
private void send(byte[] command) throws Exception
|
{
|
socket.getOutputStream().write(command);
|
socket.getOutputStream().flush();
|
}
|
|
|
|
private Diamond_Message receive() throws Exception
|
{
|
boolean salir = false;
|
int res = 0;
|
byte[] trama = null;
|
|
int longitud = 0;
|
int apuntador = 0;
|
|
try
|
{
|
while ((res = is.read()) == 0){sleep(10);};
|
|
trama = new byte[65535];
|
trama[apuntador] = (byte)res;
|
apuntador++;
|
res = is.read();
|
|
while (true)
|
{
|
trama[apuntador] = (byte)res;
|
apuntador++;
|
res = is.read();
|
}
|
}
|
catch (SocketTimeoutException e)
|
{
|
if (apuntador > 0)
|
{
|
longitud = apuntador;
|
}
|
else
|
throw e;
|
}
|
catch (Exception e)
|
{
|
throw e;
|
}
|
|
byte[] resultado = new byte[longitud];
|
System.arraycopy(trama, 0, resultado, 0, longitud);
|
|
Diamond_Message message = new Diamond_Message();
|
message.setData(resultado);
|
return(message);
|
}
|
|
|
private void checkListSize()
|
{
|
if (lvehicle.size() > MAX_VEHICLES)
|
{
|
int number = lvehicle.size() - MAX_VEHICLES;
|
for (int i=0; i<number; i++)
|
{
|
lvehicle.remove(0);
|
}
|
}
|
}
|
|
|
private void logVehicle (Etd etdclone, EtdStatusVehicle vehicle)
|
{
|
try
|
{
|
String sline = Device.getDate(System.currentTimeMillis()) + ": " + etdclone.getIdentifier() + " - TS: " + new Date(vehicle.timestamp) + " - Lane: " + vehicle.lane + " - Speed " + vehicle.speed + " - Length: " + vehicle.length + " - Axles: " + vehicle.axles + "\r\n";
|
FileOutputStream fos = new FileOutputStream(new File("etd/" + etdclone.getIdentifier() + ".dat"), true);
|
fos.write(sline.getBytes());
|
fos.flush();
|
fos.close();
|
fos = null;
|
}
|
catch (Exception e)
|
{
|
e.printStackTrace();
|
}
|
}
|
}
|