/**
*
* Copyright (c) 2009-2016 Freedomotic team http://freedomotic.com
*
* This file is part of Freedomotic
*
* This Program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2, or (at your option) any later version.
*
* This Program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* Freedomotic; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
package clientjava.connections;
import clientjava.openwebnet.OWN;
import com.freedomotic.plugins.devices.openwebnet.OpenWebNet;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.logging.*;
/**
*
* @author Maurizio Lorenzoni (loremaur@libero.it)
*/
public class CommandsSocketManager {
//THREAD DI SUPPORTO
static ReadThread readTh = null; //thread per la ricezione dei caratteri inviati dal webserver
static TimerThread timeoutThread = null; //thread per la gestione dei timeout
//STATO
static String responseLine = null; //stringa in ricezione dal Webserver
int stato = 0; //stato socket comandi
//SUPPORTO
static final String socketComandi = "*99*0##"; //messaggio comando per server
Socket socket = null;
BufferedReader input = null;
PrintWriter output = null;
OWN openWebNet = null; //supporto per l' OpenWebNet
//LOGGING
private static Logger logger;
private static FileHandler fh;
private OpenWebNet pluginRef;
public CommandsSocketManager(OpenWebNet pluginRef) {
this.pluginRef = pluginRef;
}
/**
* Si occupa dell' handshaking di sessioni comando.
*
* Apre una socket con il client (se possibile) e rende possibile il metodo
* inviaComando (sulla stessa socket creata).
*
* Tentativo di apertura socket comandi verso il webserver Diversi possibili
* stati: stato 0 = non connesso stato 1 = inviata richiesta socket comandi,
* in attesa di risposta stato 2 = inviato risultato sulle operazioni della
* password, attesa per ack o nack. Se la risposta e' ack si passa allo
* stato 3 stato 3 = connesso correttamente
*
* @param ip Ip del webserver al quale connettersi
* @param port Porta sulla quale aprire la connessione
* @param passwordOpen Password open del webserver
* @return true Se la connessione va a buon fine, false altrimenti
*/
public boolean connect(String ip, int port, long password) {
try {
//opens a socket
pluginRef.getLogger().info("Tentativo connessione a " + ip + " Port: " + port);
socket = new Socket(ip, port);
//preparo stream di lettura/scrittura
setTimeout(0);
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pluginRef.getLogger().debug("Buffer reader creato");
output = new PrintWriter(socket.getOutputStream(), true);
pluginRef.getLogger().debug("Print Writer creato");
} catch (IOException e) {
pluginRef.getLogger().error("Server connection error");
this.disconnect();
}
//uso la socket aperta
if (socket != null) {
while (true) {
//ASPETTO DI AVERE QUALCOSA IN RESPONSELINE
readTh = null;
readTh = new ReadThread(socket, input, 0);
readTh.start(); //leggo la prima risposta del server
try {
readTh.join(); //aspetto di aver letto --> verrà copiata in responseLine
} catch (InterruptedException e1) {
pluginRef.getLogger().error("----- ERRORE readThread.join() durante la connect:");
e1.printStackTrace();
}
//riempito responseLine, a seconda
//dello stato in cui sono nel'handshake mi comporto diversamente
if (responseLine != null) {
if (stato == 0) { //ho mandato la richiesta di connessione
pluginRef.getLogger().debug("\n----- STATO 0 ----- ");
pluginRef.getLogger().debug("Rx: " + responseLine);
//1.2- attendo messaggio ACK (per 30 sec)
if (responseLine.equals(OWN.MSG_OPEN_OK)) {//controllo ACK
pluginRef.getLogger().debug("--- Stabilita comunicazione TCP/IP con il server.");
//2.1 invia il codice *99*0## e rimane in attesa
pluginRef.getLogger().debug("Tx: " + socketComandi);
output.write(socketComandi); //comandi (invio codice al server)
output.flush();
stato = 1;
setTimeout(0);
} else { //caso NACK
//se non mi connetto chiudo la socket
pluginRef.getLogger().debug("--- Comunicazione TCP/IP con il server non riuscita.");
pluginRef.getLogger().debug("Chiudo la socket verso il server ");
this.disconnect();
break;
}
} else if (stato == 1) { //ho mandato il tipo di servizio richiesto
pluginRef.getLogger().debug("\n----- STATO 1 -----");
pluginRef.getLogger().debug("Rx: " + responseLine);
//controllo password disattivato
/*
* if(GestoreConnessioniAdapter.abilitaPass.isSelected()){
* //applico algoritmo di conversione
* logger.log(Level.CONFIG, "Controllo sulla password");
* long risultato =
* gestPassword.applicaAlgoritmo(passwordOpen,
* responseLine); logger.log(Level.CONFIG, "Tx:
* "+"*#"+risultato+"##",1,0,0);
* output.write("*#"+risultato+"##"); output.flush();
* stato = 2; //setto stato dopo l'autenticazione
* setTimeout(0); }else{
*/
//non devo fare il controllo della password
pluginRef.getLogger().debug("NON effettuo il controllo sulla password - mi aspetto ACK");
//2.6 se entro 30 sec non ricevo ACK -> chiudo la connessione
if (responseLine.equals(OWN.MSG_OPEN_OK)) {
pluginRef.getLogger().debug("--- Stabilita sessione comandi con il server.");
pluginRef.getLogger().debug("Ricevuto ack, stato = 3");
stato = 3;
break;
} else {
pluginRef.getLogger().debug("Impossibile connettersi!!");
pluginRef.getLogger().debug("--- Sessione comandi con il server non stabilita.");
//se non mi connetto chiudo la socket
pluginRef.getLogger().debug("Chiudo la socket verso il server ");
this.disconnect();
break;
}
//}
} else if (stato == 2) { //attesa password (disattivato)
pluginRef.getLogger().debug("\n----- STATO 2 -----");
pluginRef.getLogger().debug("Rx: " + responseLine);
if (responseLine.equals(OWN.MSG_OPEN_OK)) {
pluginRef.getLogger().debug("Connessione OK");
stato = 3;
break;
} else {
pluginRef.getLogger().error("Impossibile connettersi!!");
//se non mi connetto chiudo la socket
pluginRef.getLogger().debug("Chiudo la socket verso il server ");
this.disconnect();
break;
}
} else {
break; //non dovrebbe servire (quando passo per lo stato tre esco dal ciclo con break)
}
} else {
pluginRef.getLogger().debug("--- Risposta dal webserver NULL");
this.disconnect();
break;//ramo else di if(responseLine != null)
}
}//chiude while(true)
} else {
}
if (stato == 3) {
return true;
} else {
return false;
}
}
/**
* Chiude la socket comandi ed imposta stato = 0
*
*/
public void disconnect() {
if (socket != null) {
try {
socket.close();
socket = null;
stato = 0;
pluginRef.getLogger().debug("-----Socket chiusa correttamente-----");
pluginRef.getLogger().debug("--- Chiusa sessione comandi con il server.");
} catch (IOException e) {
pluginRef.getLogger().debug("Errore Socket: <GestioneSocketComandi>");
e.printStackTrace();
}
}
}
/**
* Metodo per l'invio di un comando open una volta aperta la socket con il
* metodo connect
*
* @param comandoOpen comando da inviare
* @return 0 se il comando vine inviato, 1 se non è possibile inviare il
* comando
*/
public int inviaComando(String comandoOpen) {
//creo l'oggetto openWebNet con il comandoOpen
try {
openWebNet = new OWN(comandoOpen);
if (openWebNet.isErrorFrame()) {
pluginRef.getLogger().error("ERRATA frame open " + comandoOpen + ", la invio comunque!!!");
} else {
pluginRef.getLogger().debug("CREATO oggetto OpenWebNet " + openWebNet.getFrameOpen());
}
} catch (Exception e) {
pluginRef.getLogger().error("ERRORE nella creazione dell'oggetto OpenWebNet " + comandoOpen);
pluginRef.getLogger().error("Eccezione in GestioneSocketComandi durante la creazione del'oggetto OpenWebNet");
e.printStackTrace();
}
//3.1 invia il messaggio open e rimane in attesa della risposta (ACK/NACK) del server
pluginRef.getLogger().debug("Tx: " + comandoOpen);
output.write(comandoOpen);
output.flush();
do {
setTimeout(0);
readTh = null;
readTh = new ReadThread(socket, input, 0);
readTh.start(); //attendo risposta dal server
try {
readTh.join();
} catch (InterruptedException e1) {
pluginRef.getLogger().error("----- ERRORE readThread.join() durante l'invio comando:");
e1.printStackTrace();
}
//3.2 la risposta può essere ACK(*#*1##) o NACK(*#*0##)
if (responseLine != null) {
if (responseLine.equals(OWN.MSG_OPEN_OK)) {//ACK
pluginRef.getLogger().debug("Rx: " + responseLine);
pluginRef.getLogger().debug("Comando inviato correttamente");
this.disconnect();//chiudo connessione
return 0;
//break;
} else if (responseLine.equals(OWN.MSG_OPEN_KO)) {//NACK
pluginRef.getLogger().debug("Rx: " + responseLine);
pluginRef.getLogger().error("Comando NON inviato correttamente");
//if(!ClientFrame.mantieniSocket.isSelected()) this.disconnect();
this.disconnect();//chiudo connessione
return 0;
//break;
} else {
//RICHIESTA STATO
System.out.println("Rx: " + responseLine);
if (responseLine == OWN.MSG_OPEN_OK) {
pluginRef.getLogger().debug("Comando inviato correttamente");
this.disconnect();//chiudo connessione
return 0;
//break;
} else if (responseLine == OWN.MSG_OPEN_KO) {
pluginRef.getLogger().error("Comando NON inviato correttamente");
this.disconnect();//chiudo connessione
return 0;
//break;
}
}
} else {
pluginRef.getLogger().error("Impossibile inviare il comando");
this.disconnect();//chiudo connessione
return 1;
//break;
}
} while (true);
}
/**
* Attiva il thread per il timeout sulla risposta inviata dal WebServer.
*
* @param tipoSocket: 0 se è socket comandi, 1 se è socket monitor
*/
public void setTimeout(int tipoSocket) {
timeoutThread = null;
timeoutThread = new TimerThread("timeout", tipoSocket, pluginRef);
timeoutThread.start();
}
}