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 lrequest = new ArrayList(); 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 () { // Shared.traceInformation(name, Shared.getMessage("Starting")); // 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){}; } } // Shared.traceInformation(name, Shared.getMessage("Finishing")); // } 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 lremove = new ArrayList(); 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= 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){}; } } }