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.transactions.traces.Trace;
import art.library.utils.synchro.Mutex;
import art.servers.etdserver.Shared;
import art.servers.etdserver.protocols.skp3.SKP3_Message;
import art.servers.etdserver.protocols.skp3.SKP3_ProtocolAnalyser;
import art.servers.etdserver.protocols.skp3.SKP3_ProtocolConstructor;
import art.servers.etdserver.protocols.skp3.SKP3_ProtocolWriter;
import java.io.InputStream;
import java.io.OutputStream;
import static java.lang.Thread.sleep;
import java.net.Socket;
import java.text.SimpleDateFormat;
public class ControllerSKP3 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 long lastTimestamp = 0;
private int status = DeviceStatus.STATUS_ALARM;
private boolean firstTime = true;
private Mutex mutexPort = new Mutex();
public ControllerSKP3(Etd etd)
{
super(etd);
this.device = etd;
this.name = Shared.getMessage("Controller etd") + " " + etd.information.name;
super.setName(this.name);
}
public void run()
{
//
art.servers.Shared.println(Trace.getTraceInformation(art.servers.Shared.getApplicationName(), name, art.servers.Shared.getMessage("Starting"), art.servers.Shared.getMessage("Success")), true);
//
while ((isInterrupted() == false) && (exit == false))
{
long startTimestamp = System.currentTimeMillis();
try
{
if (art.servers.Shared.isServerEnabled() == true)
{
// if (connected == false)
// {
// connect();
// }
update();
}
}
catch (Exception e)
{
}
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)
{
}
}
try
{
sleep(1000);
}
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;
}
}
//
art.servers.Shared.println(Trace.getTraceInformation(art.servers.Shared.getApplicationName(), name, art.servers.Shared.getMessage("Finishing"), art.servers.Shared.getMessage("Success")), true);
//
}
/*
Private controller functions
*/
private void update() throws Exception
{
Etd etdclone = (Etd)Serialization.clone(device);
try
{
sleep(5000);
EtdInformation etdInformation = (EtdInformation)etdclone.getDeviceInformation();
// Update serial number
{
readSerialNumber(etdclone);
}
// Status / Alarms
{
readStatus(etdclone);
}
// Data
{
readCurrentTrafficDataPeriod(etdclone);
}
online(etdclone);
return;
}
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);
}
offline(etdclone);
try{disconnect();} catch (Exception ex){};
}
}
private boolean isError()
{
errorsNumber = errorsNumber + 1;
if (errorsNumber >= maxErrorsNumber)
return(true);
return(false);
}
private void offline(Etd etdclone)throws Exception
{
if (isError() == true)
{
if (etdclone.getAlarm("alarm_offline") <= 0)
{
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
{
errorsNumber = 0;
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 readSerialNumber (Etd etdclone) throws Exception
{
byte[] command = SKP3_ProtocolConstructor.readSerialNumber(0x00);
SKP3_Message response = read(command);
int serialNumber = SKP3_ProtocolAnalyser.analyseReadSerialNumberResponse(response);
if (etdclone.getDeviceInformation().serialNumber.equalsIgnoreCase(""+serialNumber) == false)
{
etdclone.getDeviceInformation().serialNumber = ""+serialNumber;
}
}
private void readStatus (Etd etdclone) throws Exception
{
byte[] command = SKP3_ProtocolConstructor.readStatus(Integer.parseInt(etdclone.getDeviceInformation().serialNumber));
SKP3_Message response = read(command);
SKP3_ProtocolAnalyser.analyseReadStatusResponse(etdclone, response);
}
private void readCurrentTrafficDataPeriod (Etd etdclone) throws Exception
{
byte[] command = SKP3_ProtocolConstructor.readCurrentTrafficData(Integer.parseInt(etdclone.getDeviceInformation().serialNumber), 0, 1);
SKP3_Message response = read(command);
SKP3_ProtocolAnalyser.analyseReadCurrentTrafficDataPeriodResponse(etdclone, response);
}
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 SKP3_Message read(byte[] command) throws Exception
{
try
{
//send(command);
//return receive();
mutexPort.lockWrite();
try
{
connect();
send(command);
return receive();
}
catch (Exception e)
{
throw e;
}
finally
{
disconnect();
mutexPort.releaseWrite();
}
}
catch (Exception e)
{
throw e;
}
}
private void send(byte[] command) throws Exception
{
socket.getOutputStream().write(command);
socket.getOutputStream().flush();
}
private SKP3_Message receive() throws Exception
{
boolean salir = false;
int res = 0;
byte[] trama = null;
int longitud = 0;
long ts = System.currentTimeMillis();
try
{
while ((res = is.read()) == 0){sleep(10);};
if (res != SKP3_ProtocolWriter.STX)
{
while ((res != SKP3_ProtocolWriter.STX) && (res != -1) && ((System.currentTimeMillis()-ts) <= device.getDeviceInformation().connection.timeout))
{
res = is.read();
}
}
if (res == SKP3_ProtocolWriter.STX)
{
ts = System.currentTimeMillis();
int apuntador = 0;
trama = new byte[65535];
trama[apuntador] = (byte)res;
apuntador++;
res = is.read();
while ((res != SKP3_ProtocolWriter.STX) && (res != -1) && ((System.currentTimeMillis()-ts) <= device.getDeviceInformation().connection.timeout))
{
trama[apuntador] = (byte)res;
apuntador++;
res = is.read();
}
trama[apuntador] = (byte)res;
apuntador++;
longitud = apuntador;
}
}
catch (Exception e)
{
throw e;
}
if ((res == -1) || (longitud == 0))
throw new Exception("Timeout-Error");
byte[] resultado = new byte[longitud];
System.arraycopy(trama, 0, resultado, 0, longitud);
SKP3_Message message = new SKP3_Message();
message.setData(resultado);
return(message);
}
}