package art.servers.colorsserver.controller;
|
|
import art.library.model.devices.Device;
|
import art.library.utils.synchro.Mutex;
|
import art.servers.ColorsServer;
|
import art.servers.ServerException;
|
import art.servers.colorsserver.Shared;
|
import art.servers.colorsserver.M.protocol.M_Message;
|
import static art.servers.colorsserver.M.protocol.M_ProtocolWriter.*;
|
import art.servers.colorsserver.M.protocol.M_Request;
|
import art.servers.controller.Controller;
|
import java.io.InputStream;
|
import java.io.OutputStream;
|
import java.net.Socket;
|
import java.net.SocketException;
|
import java.net.SocketTimeoutException;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
|
public class ControllerConnection extends Controller
|
{
|
private String name = "";
|
public String address = null;
|
private int port = 0;
|
private int timeout = 0;
|
private boolean hasCRC = false;
|
public Socket socket = null;
|
private InputStream is = null;
|
private OutputStream os = null;
|
private boolean connected = false;
|
private Mutex mutexListRequest = new Mutex();
|
private List<M_Request> lrequest = new ArrayList<M_Request>();
|
private int timeouts = 0;
|
private int maxtimeouts = 50;
|
private int reconnections = 0;
|
private boolean print = false;
|
private boolean trace = false;
|
private boolean execute = true;
|
|
|
public ControllerConnection (String address, int port, int timeout, boolean hasCRC)
|
{
|
this.address = address;
|
this.port = port;
|
this.timeout = timeout;
|
this.hasCRC = hasCRC;
|
this.name = Shared.getMessage("Controller connection") + " " + this.address + ":" + this.port + "," + this.timeout + "," + this.hasCRC;
|
this.setName(name);
|
print = (this.address.equalsIgnoreCase(Shared.ipcontrollerlog) && (this.port == Shared.portcontrollerlog));
|
trace = (this.address.equalsIgnoreCase(Shared.ipcontrollerlog) && (this.port == Shared.portcontrollerlog) && (ColorsServer.LOG_TRACE == true));
|
}
|
|
|
|
|
public void run ()
|
{
|
// <editor-fold defaultstate="collapsed" desc="Trace">
|
Shared.traceInformation(name, Shared.getMessage("Starting"));
|
// </editor-fold>
|
|
while ((isInterrupted() == false) && (exit == false))
|
{
|
try
|
{
|
if (this.execute == true)
|
{
|
connect();
|
|
long millis = System.currentTimeMillis();
|
clearM_Request();
|
if (lrequest.size() > 10)
|
{
|
Shared.println(name, Device.getDate(System.currentTimeMillis()) + " - " + address + ":" + port + " - 0.RCV: " + (System.currentTimeMillis()-millis) + " - " + lrequest.size());
|
}
|
|
if (this.connected == true)
|
{
|
M_Message response = receive();
|
ack();
|
|
M_Request request = getM_Request(response);
|
if (request != null)
|
{
|
if (print == true)
|
{
|
Shared.println(name, Device.getDate(System.currentTimeMillis()) + " - " + this.address + ":" + this.port + " - Received message Request: " + response);
|
if (trace == true)
|
{
|
Shared.traceInformation(name, "Received message Response", response.toString());
|
}
|
}
|
removeM_Request(request, response);
|
}
|
else
|
{
|
// Notification
|
if (print == true)
|
{
|
Shared.println(name, Device.getDate(System.currentTimeMillis()) + " - " + this.address + ":" + this.port + " - Received message Notification: " + response);
|
if (trace == true)
|
{
|
Shared.traceInformation(name, "Received message Notification", response.toString());
|
}
|
}
|
}
|
}
|
else
|
{
|
String message = "DISCON.Run " + address + ":" + port + " - " + this.connected;
|
Shared.println(this.getName(), message);
|
}
|
}
|
}
|
catch (Exception e)
|
{
|
if (e.toString().toUpperCase().indexOf("NULLPOINTER") < 0)
|
{
|
Shared.println(this.getName(), e);
|
}
|
}
|
finally
|
{
|
try{sleep(50);} catch (Exception exception){};
|
}
|
}
|
|
// <editor-fold defaultstate="collapsed" desc="Trace">
|
Shared.traceInformation(name, Shared.getMessage("Finishing"));
|
// </editor-fold>
|
}
|
|
|
public void stopConnection ()
|
{
|
try
|
{
|
execute = false;
|
disconnect();
|
}
|
catch (Exception e)
|
{
|
|
}
|
}
|
|
|
public void resumeconnection ()
|
{
|
try
|
{
|
execute = true;
|
}
|
catch (Exception e)
|
{
|
|
}
|
}
|
|
|
public void setTimeout (int timeout)
|
{
|
try
|
{
|
socket.setSoTimeout(timeout);
|
}
|
catch (Exception e)
|
{
|
|
}
|
}
|
|
|
private void clearM_Request ()
|
{
|
try
|
{
|
mutexListRequest.lockWrite();
|
List<M_Request> lremove = new ArrayList<M_Request>();
|
for (M_Request request : lrequest)
|
{
|
if (request.finishedByTimeout == true)
|
{
|
lremove.add(request);
|
}
|
}
|
|
if (lremove.size() > 0)
|
{
|
lrequest.removeAll(lremove);
|
}
|
}
|
catch (Exception e)
|
{
|
|
}
|
finally
|
{
|
mutexListRequest.releaseWrite();
|
}
|
}
|
|
|
public void addM_Request (M_Request request)
|
{
|
try
|
{
|
mutexListRequest.lockWrite();
|
send(request.request.toByteArray());
|
request.send(timeout);
|
lrequest.add(request);
|
}
|
catch (Exception e)
|
{
|
|
}
|
finally
|
{
|
mutexListRequest.releaseWrite();
|
}
|
}
|
|
|
private void removeM_Request (M_Request request, M_Message response)
|
{
|
try
|
{
|
mutexListRequest.lockWrite();
|
if (response != null) request.receive(response);
|
lrequest.remove(request);
|
}
|
catch (Exception e)
|
{
|
|
}
|
finally
|
{
|
mutexListRequest.releaseWrite();
|
}
|
}
|
|
|
private M_Request getM_Request (M_Message response)
|
{
|
try
|
{
|
mutexListRequest.lockRead();
|
// if ((response.isAck == true) || (response.isNack == true) || (response.isTrcam == true))
|
// return null;
|
if ((response.isNack == true) || (response.isTrcam == true))
|
return null;
|
|
if (print == true)
|
{
|
Shared.println(name, Device.getDate(System.currentTimeMillis()) + " - " + this.address + ":" + this.port + " - " + response.controller + " - " + response.table + " - Analyzing message reception: " + response);
|
}
|
|
for (M_Request request : lrequest)
|
{
|
if (response.isAck == true)
|
{
|
if (request.finishedByTimeout == false)
|
{
|
switch(request.request.directive)
|
{
|
case M_WRITE_TABLE_FULL:
|
{
|
if (print == true)
|
{
|
Shared.println(name, "Received write full table, ACK: " + request.request.directive + " - " + request.request.controller + " - " + request.request.table);
|
}
|
|
// There is a request pending
|
return(request);
|
}
|
}
|
}
|
}
|
else
|
{
|
if ((request.finishedByTimeout == false) &&
|
(request.request.controller == response.controller) &&
|
(request.request.table == response.table))
|
{
|
if (request.request.isCountingDetectorQuery() == true)
|
{
|
if (response.directive == M_CURRENT_COUNTING_DETECTORS)
|
{
|
return(request);
|
}
|
}
|
|
if (request.request.isPRHQuery()== true)
|
{
|
if (response.directive == M_CURRENT_TIME_QUERY)
|
{
|
return(request);
|
}
|
}
|
|
switch(request.request.directive)
|
{
|
case M_RECORDABLE_PLAN_QUERY:
|
{
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_CURRENT_PLAN_QUERY:
|
{
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_CURRENT_TIME_QUERY:
|
{
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_CURRENT_SUBCONTROLLER_STATE_QUERY:
|
{
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_CURRENT_PRESENCE_DETECTORS:
|
{
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_CURRENT_COUNTING_DETECTORS_DATETIME:
|
{
|
}
|
break;
|
|
case M_CURRENT_COUNTING_DETECTORS:
|
{
|
if (request.request.isCountingDetectorQuery() == true)
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_ALARMS_QUERY:
|
{
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_BLOWN_LAMPS_ALARMS_QUERY:
|
{
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_DAMAGED_GROUP_ALARMS_QUERY:
|
{
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_INCOMPATIBILITY_ALARMS_QUERY:
|
{
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_CURRENT_STATUS_GROUPS_QUERY:
|
{
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_READ_TABLE_FULL:
|
{
|
if (print == true)
|
{
|
Shared.println(name, "Received read full table: " + request.request.directive + " - " + response.directive + " - " + request.request.controller + " - " + response.controller + " - " + request.request.table + " - " + response.table);
|
}
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller) &&
|
(request.request.table == response.table))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_WRITE_TABLE_FULL:
|
{
|
if (print == true)
|
{
|
Shared.println(name, "Received write full table: " + request.request.directive + " - " + response.directive + " - " + request.request.controller + " - " + response.controller + " - " + request.request.table + " - " + response.table);
|
}
|
if ((request.request.directive == response.directive) &&
|
(request.request.controller == response.controller) &&
|
(request.request.table == response.table))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_START_RECORDING:
|
{
|
if (print == true)
|
{
|
Shared.println(name, "Received start recording tables: " + request.request.directive + " - " + response.directive + " - " + request.request.controller + " - " + response.controller + " - " + request.request.table + " - " + response.table);
|
}
|
if ((response.directive == M_START_RECORDING_RESPONSE) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
|
case M_END_RECORDING:
|
{
|
if (print == true)
|
{
|
Shared.println(name, "Received end recording tables: " + request.request.directive + " - " + response.directive + " - " + request.request.controller + " - " + response.controller + " - " + request.request.table + " - " + response.table);
|
}
|
if ((response.directive == M_END_RECORDING_RESPONSE) &&
|
(request.request.controller == response.controller))
|
{
|
// There is a request pending
|
return(request);
|
}
|
}
|
break;
|
}
|
}
|
}
|
}
|
}
|
catch (Exception e)
|
{
|
Shared.printstack(name, e);
|
}
|
finally
|
{
|
mutexListRequest.releaseRead();
|
}
|
|
return(null);
|
}
|
|
|
|
|
public void connect()
|
{
|
try
|
{
|
if (socket != null)
|
{
|
if (this.connected == true)
|
{
|
return;
|
}
|
}
|
|
socket = new Socket(address, port);
|
socket.setSoTimeout(timeout);
|
is = socket.getInputStream();
|
os = socket.getOutputStream();
|
|
if (this.connected == true)
|
{
|
String message = "Connected " + address + ":" + port + " - " + this.timeout;
|
Shared.println(this.getName(), message);
|
}
|
|
this.connected = true;
|
this.reconnections = this.reconnections + 1;
|
}
|
catch (Exception e)
|
{
|
Shared.println(name, Device.getDate(System.currentTimeMillis()) + " - " + address + ":" + port + " " + timeout + " - Exception : " + e.toString());
|
Shared.println(this.getName(), e);
|
try{disconnect();} catch (Exception ex){};
|
}
|
}
|
|
|
|
|
public void disconnect() throws ServerException, 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;
|
|
if (this.connected == true)
|
{
|
String message = "Disconnected " + address + ":" + port + " - " + this.timeout;
|
Shared.println(this.getName(), message);
|
}
|
|
this.connected = false;
|
}
|
|
|
|
public M_Message read(byte[] command) throws ServerException, Exception
|
{
|
try
|
{
|
send(command);
|
M_Message message = receive();
|
if (print == true)
|
{
|
String s = this.address + ":" + this.port + " << ";
|
Shared.println(name, Device.getDate(System.currentTimeMillis()) + " - " + s + message);
|
if (trace == true)
|
{
|
Shared.traceInformation(name, message.toString());
|
}
|
}
|
return message;
|
}
|
catch (SocketException e)
|
{
|
if (print == true)
|
{
|
Shared.printstack(name, e);
|
if (trace == true)
|
{
|
Shared.traceError(name, "Read", e);
|
}
|
}
|
|
disconnect();
|
throw e;
|
}
|
catch (Exception e)
|
{
|
throw e;
|
}
|
}
|
|
|
|
public void send(byte[] command) throws ServerException, Exception
|
{
|
if (print == true)
|
{
|
String s = this.address + ":" + this.port + " >>>>> ";
|
String scommand = " >> ";
|
for (int i=0; i<command.length; i++)
|
{
|
s += String.format("$%02X", command[i]);
|
scommand += String.format("$%02X", command[i]);
|
}
|
Shared.println(name, Device.getDate(System.currentTimeMillis()) + " - " + s);
|
if (trace == true)
|
{
|
Shared.traceInformation(name, scommand);
|
}
|
}
|
socket.getOutputStream().write(command);
|
socket.getOutputStream().flush();
|
}
|
|
|
|
public M_Message receive() throws ServerException, Exception
|
{
|
boolean salir = false;
|
int res = 0;
|
byte[] trama = null;
|
|
int longitud = 0;
|
|
try
|
{
|
while ((res = is.read()) == 0){sleep(10);};
|
|
if (res != -1)
|
{
|
if (res == 0x11)
|
{
|
while (res == 0x11)
|
{
|
res = is.read();
|
}
|
}
|
|
if (res == 0x06)
|
{
|
M_Message message = new M_Message();
|
message.isAck = true;
|
int[] data = new int[1];
|
data[0] = res;
|
message.setData(data);
|
return(message);
|
}
|
|
if (res == 0x15)
|
{
|
M_Message message = new M_Message();
|
message.isNack = true;
|
int[] data = new int[1];
|
data[0] = res;
|
message.setData(data);
|
return(message);
|
}
|
|
if ((res >= 0x30) && (res <= 0x3F))
|
{
|
M_Message message = new M_Message();
|
message.isTrcam = true;
|
int[] data = new int[1];
|
data[0] = res;
|
message.setData(data);
|
return(message);
|
}
|
|
if (res == 0x02)
|
{
|
int apuntador = 0;
|
trama = new byte[4096];
|
trama[apuntador] = (byte)res;
|
apuntador++;
|
|
// Obtenemos todos los datos disponibles
|
while (res != 0x03)
|
{
|
res = is.read();
|
trama[apuntador] = (byte)res;
|
apuntador++;
|
}
|
|
longitud = apuntador;
|
}
|
}
|
}
|
catch (SocketTimeoutException e)
|
{
|
this.timeouts = this.timeouts + 1;
|
if (this.timeouts >= this.maxtimeouts)
|
{
|
Shared.println(name, Device.getDate(System.currentTimeMillis()) + " - " + this.address + ":" + this.port + " - 1.TIMEOUTS: " + this.timeouts + " - " + e.bytesTransferred + " - RES: " + res);
|
this.timeouts = 0;
|
Shared.printstack(name, e);
|
disconnect();
|
throw new Exception(Shared.getMessage("Timeout Error"));
|
}
|
}
|
catch (Exception e)
|
{
|
Shared.printstack(name, e);
|
disconnect();
|
throw e;
|
}
|
|
if (res == -1)
|
{
|
this.timeouts = this.timeouts + 1;
|
if (this.timeouts >= this.maxtimeouts)
|
{
|
Shared.println(name, Device.getDate(System.currentTimeMillis()) + " - " + this.address + ":" + this.port + " - 2.TIMEOUTS: " + this.timeouts);
|
this.timeouts = 0;
|
disconnect();
|
}
|
|
throw new Exception(Shared.getMessage("Timeout Error"));
|
}
|
|
this.timeouts = 0;
|
|
// Enviamos el resultado
|
byte[] resultado = new byte[longitud];
|
System.arraycopy(trama, 0, resultado, 0, longitud);
|
M_Message message = new M_Message();
|
message.setData(resultado);
|
message.fillInformation();
|
return(message);
|
}
|
|
|
public void ack()
|
{
|
if (this.hasCRC == true)
|
{
|
byte[] ack = {0x06};
|
try{send(ack);} catch (Exception e){};
|
}
|
}
|
|
}
|