/**
* Copyright (c) 2010-2015, openHAB.org and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.myhome.fcrisciani.connector;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
/**
* The MyHomeSocketFactory is a static class that permits to easily create
* sockets able to communicate with a MyHome plant
*
* @author Flavio Crisciani
* @serial 1.0
* @since 1.7.0
*/
public class MyHomeSocketFactory {
// ----- TYPES ----- //
// ---- MEMBERS ---- //
final static String socketCommand = "*99*0##"; // OpenWebNet command to ask
// for a command session
final static String socketMonitor = "*99*1##"; // OpenWebNet command to ask
// for a monitor session
// ---- METHODS ---- //
/**
* Reads a well formed message from the input stream passed and return it
* back
*
* @param inputStream
* steam to read from
* @return the message read
* @throws IOException
* in case of problem with the input stream, close the stream
*/
protected static String readUntilDelimiter(final BufferedReader inputStream)
throws IOException, SocketTimeoutException {
StringBuffer response = new StringBuffer();
int ci = 0;
char c = ' ';
Boolean canc = false;
// Cycle that reads one char each cycle and stop when the sequence ends
// with ## that is the OpenWebNet delimiter of each message
do {
ci = inputStream.read();
if (ci == -1) {
System.err.println("Socket already closed by server \n");
inputStream.close();
throw new IOException();
} else {
c = (char) ci;
if (c == '#' && canc == false) { // Found first #
response.append(c);
canc = true;
} else if (c == '#') { // Found second # command terminated
// correctly EXIT
response.append(c);
break;
} else if (c != '#') { // Append char and start again finding
// the first #
response.append(c);
canc = false;
}
}
} while (true);
return response.toString();
}
/**
* Reads multiple messages from the input stream and returns them back in an
* array
*
* @param inputStream
* steam to read from
* @return an array of messages
* @throws IOException
* in case of problem with the input stream, close the stream
*/
protected static String[] readUntilAckNack(final BufferedReader inputStream) throws IOException {
ArrayList<String> result = new ArrayList<String>();
String commandReceived = null;
// Call multiple times the previous function to read more messages.
// A sequence of multiple messages end always with an ACK or NACK so
// stop this cycle when the message is one of them
do {
commandReceived = readUntilDelimiter(inputStream);
result.add(commandReceived);
} while (commandReceived != null && isACK(commandReceived) != true && isNACK(commandReceived) != true);
return result.toArray(new String[result.size()]);
}
/**
* Is used to select if the response is a positive ACK
*
* @param str
* string to be controlled
* @return true if the message is an ACK
*/
public static Boolean isACK(final String str) {
return str.contentEquals("*#*1##");
}
/**
* Is used to select if the response is a negative ACK
*
* @param str
* string to be controlled
* @return true if the message is an NACK
*/
public static Boolean isNACK(final String str) {
return str.contentEquals("*#*0##");
}
/**
* Open a command socket with the webserver specified.
*
* @param ip
* IP address of the webserver
* @param port
* of the webserver
* @return the socket ready to be used
* @throws IOException
* if there is some problem with the socket opening
*/
public static Socket openCommandSession(final String ip, final int port) throws IOException {
Socket sk = new Socket(ip, port);
BufferedReader inputStream = new BufferedReader(new InputStreamReader(sk.getInputStream()));
PrintWriter outputStream = new PrintWriter(sk.getOutputStream(), true);
String response = readUntilDelimiter(inputStream);
outputStream.write(socketCommand);
outputStream.flush();
response = readUntilDelimiter(inputStream);
if (isACK(response) != true) {
throw new IOException();
}
return sk;
}
/**
* Open a monitor socket with the webserver specified.
*
* @param ip
* IP address of the webserver
* @param port
* of the webserver
* @return the socket ready to be used
* @throws IOException
* if there is some problem with the socket opening
*/
public static Socket openMonitorSession(final String ip, final int port) throws IOException {
Socket sk = new Socket(ip, port);
sk.setSoTimeout(45 * 1000);
BufferedReader inputStream = new BufferedReader(new InputStreamReader(sk.getInputStream()));
PrintWriter outputStream = new PrintWriter(sk.getOutputStream(), true);
String response = readUntilDelimiter(inputStream);
outputStream.write(socketMonitor);
outputStream.flush();
response = readUntilDelimiter(inputStream);
if (isACK(response) != true) {
throw new IOException();
}
return sk;
}
/**
* Close the socket passed
*
* @param sk
* socket to be closed
* @throws IOException
* if there is some problem with the socket closure
*/
public static void disconnect(final Socket sk) throws IOException {
sk.close();
}
}