Update Harmonhy connection handling on disconnect. Add Route Parse

This commit is contained in:
BWS Systems
2018-11-06 15:46:45 -06:00
parent faae6aa31f
commit c9e6cd079f
6 changed files with 603 additions and 9 deletions

13
pom.xml
View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId>
<version>5.2.1a</version>
<version>5.2.2b</version>
<packaging>jar</packaging>
<name>HA Bridge</name>
@@ -63,7 +63,7 @@
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.7.1</version>
<version>2.7.2</version>
<exclusions>
<exclusion>
<artifactId>slf4j-simple</artifactId>
@@ -120,6 +120,7 @@
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.bwssytems</groupId>
@@ -156,6 +157,14 @@
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>

View File

@@ -9,6 +9,7 @@ import net.whistlingfish.harmony.HarmonyClient;
import net.whistlingfish.harmony.config.Activity;
import net.whistlingfish.harmony.config.Device;
import net.whistlingfish.harmony.config.HarmonyConfig;
import com.bwssystems.HABridge.NamedIP;
public class HarmonyHandler {
private static final Logger log = LoggerFactory.getLogger(HarmonyHandler.class);
@@ -16,8 +17,9 @@ public class HarmonyHandler {
private Boolean noopCalls;
private Boolean devMode;
private DevModeResponse devResponse;
private NamedIP myNameAndIP;
public HarmonyHandler(HarmonyClient theClient, Boolean noopCallsSetting, DevModeResponse devResponseSetting) {
public HarmonyHandler(HarmonyClient theClient, Boolean noopCallsSetting, DevModeResponse devResponseSetting, NamedIP aNameAndIP) {
super();
noopCalls = noopCallsSetting;
devMode = Boolean.TRUE;
@@ -27,6 +29,7 @@ public class HarmonyHandler {
else
devResponse = devResponseSetting;
harmonyClient = theClient;
myNameAndIP = aNameAndIP;
}
public List<Activity> getActivities() {
@@ -34,7 +37,15 @@ public class HarmonyHandler {
if(devMode)
return devResponse.getActivities();
return harmonyClient.getConfig().getActivities();
List<Activity> listOfActivities = null;
try {
listOfActivities = harmonyClient.getConfig().getActivities();
} catch (RuntimeException e) {
handleExceptionError(e);
}
return listOfActivities;
}
public List<Device> getDevices() {
@@ -42,7 +53,14 @@ public class HarmonyHandler {
if(devMode)
return devResponse.getDevices();
return harmonyClient.getConfig().getDevices();
List<Device> listOfDevices = null;
try {
listOfDevices = harmonyClient.getConfig().getDevices();
} catch (RuntimeException e) {
handleExceptionError(e);
}
return listOfDevices;
}
public HarmonyConfig getConfig() {
@@ -50,15 +68,27 @@ public class HarmonyHandler {
if(devMode)
return devResponse.getConfig();
return harmonyClient.getConfig();
HarmonyConfig aConfig = null;
try {
aConfig = harmonyClient.getConfig();
} catch (RuntimeException e) {
handleExceptionError(e);
}
return aConfig;
}
public Activity getCurrentActivity() {
log.debug("Harmony api current sctivity requested.");
if(devMode)
return devResponse.getCurrentActivity();
return harmonyClient.getCurrentActivity();
Activity anActivity = null;
try {
anActivity = harmonyClient.getCurrentActivity();
} catch (RuntimeException e) {
handleExceptionError(e);
}
return anActivity;
}
public Boolean startActivity(RunActivity anActivity) {
@@ -83,7 +113,11 @@ public class HarmonyHandler {
} catch (IllegalArgumentException ei) {
log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
return false;
} catch (RuntimeException e1) {
handleExceptionError(e1);
}
} catch (RuntimeException e1) {
handleExceptionError(e1);
}
} else {
log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
@@ -114,7 +148,11 @@ public class HarmonyHandler {
} catch (IllegalArgumentException ei) {
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub());
return false;
} catch (RuntimeException e1) {
handleExceptionError(e1);
}
} catch (RuntimeException e1) {
handleExceptionError(e1);
}
} else {
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub());
@@ -124,6 +162,18 @@ public class HarmonyHandler {
return true;
}
void handleExceptionError(Exception e) {
if(e.getMessage().equalsIgnoreCase("Failed communicating with Harmony Hub")) {
log.warn("Issue in communcicating with Harmony Hub, retrying connect....");
try {
harmonyClient.disconnect();
} catch(Exception e1) {
log.warn("Hub disconnect failed, continuing....");
}
harmonyClient.connect(myNameAndIP.getIp());
}
}
public void shutdown() {
log.debug("Harmony api shutdown requested.");
if(devMode)

View File

@@ -110,7 +110,7 @@ public class HarmonyServer {
});
harmonyClient.connect(myNameAndIP.getIp());
}
myHarmony = new HarmonyHandler(harmonyClient, noopCalls, devResponse);
myHarmony = new HarmonyHandler(harmonyClient, noopCalls, devResponse, myNameAndIP);
}
public HarmonyHandler getMyHarmony() {

View File

@@ -0,0 +1,165 @@
package com.bwssystems.HABridge.util;
import java.net.*;
import java.io.*;
import java.util.*;
/**
* Find out the local IP address and default gateway
* @author Henry Zheng
* @url http://www.ireasoning.com
*/
public class ParseRoute
{
private String _gateway;
private String _ip;
private static ParseRoute _instance;
public static void main(String[] args)
{
try
{
ParseRoute pr = ParseRoute.getInstance();
System.out.println( "Gateway: " + pr.getGateway() );
System.out.println( "IP: " + pr.getLocalIPAddress() );
}
catch(Exception e)
{
System.out.println( e);
e.printStackTrace();
}
}
private ParseRoute ()
{
parse();
}
private static boolean isWindows ()
{
String os = System.getProperty ( "os.name" ).toUpperCase ();
return os.contains( "WINDOWS" ) ;
}
private static boolean isLinux ()
{
String os = System.getProperty ( "os.name" ).toUpperCase ();
return os.contains( "LINUX" ) ;
}
public String getLocalIPAddress()
{
return _ip;
}
public String getGateway()
{
return _gateway;
}
public static ParseRoute getInstance()
{
if(_instance == null)
{
_instance = new ParseRoute();
}
return _instance;
}
private void parse()
{
if(isWindows())
{
parseWindows();
}
else if(isLinux())
{
parseLinux();
}
}
private void parseWindows()
{
try
{
Process pro = Runtime.getRuntime().exec("cmd.exe /c route print");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(pro.getInputStream()));
String line;
while((line = bufferedReader.readLine())!=null)
{
line = line.trim();
String [] tokens = Tokenizer.parse(line, ' ', true , true);// line.split(" ");
if(tokens.length == 5 && tokens[0].equals("0.0.0.0"))
{
_gateway = tokens[2];
_ip = tokens[3];
return;
}
}
//pro.waitFor();
}
catch(IOException e)
{
System.err.println(e);
e.printStackTrace();
}
}
private void parseLinux()
{
BufferedReader reader = null;
try
{
reader = new BufferedReader(new FileReader("/proc/net/route"));
String line;
while((line = reader.readLine())!=null)
{
line = line.trim();
String [] tokens = Tokenizer.parse(line, '\t', true , true);// line.split(" ");
if(tokens.length > 1 && tokens[1].equals("00000000"))
{
String gateway = tokens[2]; //0102A8C0
if(gateway.length() == 8)
{
String[] s4 = new String[4];
s4[3] = String.valueOf(Integer.parseInt(gateway.substring(0, 2), 16));
s4[2] = String.valueOf(Integer.parseInt(gateway.substring(2, 4), 16));
s4[1] = String.valueOf(Integer.parseInt(gateway.substring(4, 6), 16));
s4[0] = String.valueOf(Integer.parseInt(gateway.substring(6, 8), 16));
_gateway = s4[0] + "." + s4[1] + "." + s4[2] + "." + s4[3];
}
String iface = tokens[0];
NetworkInterface nif = NetworkInterface.getByName(iface);
Enumeration<java.net.InetAddress> addrs = nif.getInetAddresses();
while(addrs.hasMoreElements())
{
Object obj = addrs.nextElement();
if(obj instanceof Inet4Address)
{
_ip = obj.toString();
if(_ip.startsWith("/")) _ip = _ip.substring(1);
reader.close();
return;
}
}
reader.close();
return;
}
}
}
catch(IOException e)
{
System.err.println(e);
e.printStackTrace();
}
if(reader != null) {
try {
reader.close();
} catch(Exception e) {
}
}
}
}

View File

@@ -0,0 +1,195 @@
package com.bwssystems.HABridge.util;
import java.io.*;
/**
* This class is an auto-resizable String array. It has similar methods to ArrayList
*
* @author Henry Zheng
* @url http://www.ireasoning.com
*/
public class StringArray implements Serializable
{
public static final long serialVersionUID = 42L;
public static final int DEFAULT_CAPACITY = 10;
protected String[] _strings = null;
protected int _upperBound = 0;
protected int _capacity = DEFAULT_CAPACITY;
protected int _initialSize = _capacity;
protected float _loadFactory = 1.5F;
public StringArray ()
{
this(DEFAULT_CAPACITY);
}
public StringArray( int size)
{
_capacity = size;
_initialSize = size;
_strings = new String[size];
}
public synchronized void ensureCapacity(int capacity)
{
if(_capacity < capacity)
{
_capacity = (_capacity * 3)/2 + 1;
if(_capacity < capacity)
{
_capacity = capacity;
}
String [] oldData = _strings;
_strings = new String[_capacity];
System.arraycopy(oldData, 0, _strings, 0, _upperBound);
}
}
public synchronized void add(String s)
{
if(_upperBound == _capacity )
{
resize((int) (_capacity * _loadFactory));
}
_strings[_upperBound++] = s;
}
public synchronized void add(StringArray sa)
{
for (int i = 0; i < sa.size() ; i++)
{
add(sa.get(i));
}
}
public synchronized String get(int index)
{
return _strings[index];
}
public synchronized void set(int index, String newVal)
{
_strings[index] = newVal;
}
/** Adds all elements in passed string array */
public synchronized void add(String [] strs)
{
for (int i = 0; i < strs.length ; i++)
{
add(strs[i]);
}
}
/** Resets this object. */
public synchronized void clear()
{
_capacity = _initialSize;
_strings = new String[_capacity];
_upperBound = 0;
}
public synchronized String remove(int index)
{
if(index >= _upperBound )
{
throw new IndexOutOfBoundsException();
}
String s = _strings[index];
for (int i = index; i < _upperBound - 1 ; i++)
{
_strings[i] = _strings[i + 1];
}
_upperBound --;
return s;
}
/**
* Removes the first occurance of passed str
* @return the string removed, or null if not found
*/
public synchronized String remove(String str)
{
for (int i = 0; i < _upperBound ; i++)
{
if(_strings[i].equals(str))
{
return remove(i);
}
}
return null;
}
public synchronized int size()
{
return _upperBound;
}
public synchronized boolean isEmpty()
{
return _upperBound == 0;
}
public synchronized String[] toArray()
{
String [] ret = new String[_upperBound];
for (int i = 0; i < _upperBound ; i++)
{
ret[i] = _strings[i];
}
return ret;
}
protected synchronized void resize(int newCapacity)
{
String [] as = new String[newCapacity];
for (int i = 0; i < _strings.length ; i++)
{
as[i] = _strings[i];
}
_strings = as;
_capacity = newCapacity;
}
public String toString()
{
StringBuffer buf = new StringBuffer();
for (int i = 0; i < _upperBound ; i++)
{
buf.append(_strings[i] + "\n");
}
return buf.toString();
}
public static void main(String[] args)
{
StringArray as = new StringArray();
String [] ss = null;
ss = as.toArray();
// System.out.println( "ss len="+ss.length);
// System.out.println( "ss = " + ss);
for (int i = 0; i < 10 ; i++)
{
as.add("" + i);
}
// System.out.println( "size = " + as.size());
ss = as.toArray();
for (int i = 0; i < ss.length ; i++)
{
// System.out.println( ss[i]);
}
// System.out.println( "remove 5th element.");
as.remove(5);
// System.out.println( "size = " + as.size());
ss = as.toArray();
for (int i = 0; i < ss.length ; i++)
{
// System.out.println( ss[i]);
}
}
}//end of class StringArray

View File

@@ -0,0 +1,175 @@
package com.bwssystems.HABridge.util;
/**
* This class perform similar functionality to StringTokenizer class but faster.
* The difference is StringTokenizer doesn't count empty token, but this class does.
*
* @author Henry Zheng
* @url http://www.ireasoning.com
*/
public class Tokenizer
{
private Tokenizer()
{
}
/**
* It's different from the other parse method in that it checks left and right string first, which take higer
* priority than the delimiter. For example, if left and right is ", for string a:b:1"c:d"2:3 ,
* it returns { a, b, 1"c:d"2, 3 }
* @param left the openning tag of higher priority token
* @param right the closing tag of higher priority token
* @trimEachToken if true, each token will be trim by calling String.trim()
*/
public static String[] parse(String text, char delimiter, boolean trimEachToken, String left, String right)
{
if(text == null) return null;
StringArray tokens = new StringArray();
int pos1 = -1;
int pos2 = -1;
int firstPos = -1;
while(true)
{
pos2 = text.indexOf(delimiter, firstPos + 1);
if(pos2 < 0 )
{
String str = text.substring(pos1 + 1);
if(trimEachToken )
{
str = str.trim();
}
tokens.add(str);
break;
}
if(pos2 == pos1 + 1)
{
tokens.add("");
}
else
{
int tagPos1 = text.indexOf(left, firstPos + 1);
if(tagPos1 > 0 && tagPos1 < pos2 )
{
int tagPos2 = text.indexOf(right, tagPos1 + 1);
if(tagPos2 > 0)
{
firstPos = tagPos2;
continue;
}
}
String str = text.substring(pos1 + 1, pos2);
if(trimEachToken )
{
str = str.trim();
}
tokens.add(str);
}
pos1 = pos2;
firstPos = pos1;
}
String[] ret = tokens.toArray();
return ret;
}
/**
* @trimEachToken if true, each token will be trim by calling String.trim()
*/
public static String[] parse(String text, char delimiter, boolean trimEachToken)
{
return parse(text, delimiter, trimEachToken, false);
}
/**
* @trimEachToken if true, each token will be trim by calling String.trim()
*/
public static String[] parse(String text, char delimiter, boolean trimEachToken, boolean ignoreEmptyToken)
{
if(text == null) return null;
StringArray tokens = new StringArray();
int pos1 = -1;
int pos2 = -1;
while(true)
{
pos2 = text.indexOf(delimiter, pos1 + 1);
if(pos2 < 0 )
{
String str = text.substring(pos1 + 1);
if(trimEachToken )
{
str = str.trim();
}
if(ignoreEmptyToken)
{
if(str.length() != 0) tokens.add(str);
}
else
{
tokens.add(str);
}
break;
}
if(pos2 == pos1 + 1)
{
if(!ignoreEmptyToken) { tokens.add(""); }
}
else
{
String str = text.substring(pos1 + 1, pos2);
if(trimEachToken )
{
str = str.trim();
}
if(ignoreEmptyToken)
{
if(str.length() != 0) tokens.add(str);
}
else
{
tokens.add(str);
}
}
pos1 = pos2;
}
String[] ret = tokens.toArray();
return ret;
}
/**
* Does not trim each token.
* @see #parse(String, char, boolean)
*/
public static String[] parse(String text, char delimiter)
{
return parse(text, delimiter, false);
}
// public static void main(String[] args)
// {
// String str = "1,\"2,\"ab\",ttt1,\"3,,a\"222\",4";
// if(args.length > 0)
// {
// str = args[0];
// }
// String [] tokens = Tokenizer.parse(str, ',');
//
//// System.out.println( "Text = (" + str + ")");
// // System.out.println( "------------------------------------------");
// for (int i = 0; i < tokens.length ; i++)
// {
// // System.out.println( "(" + tokens[i] + ")");
// }
// // System.out.println( "------------------------------------------");
// String [] tokens = Tokenizer.parse(str, ',', new String[]{"("}, new String[]{")"});
//
// // System.out.println( "Text = [" + str + "]");
// // System.out.println( "------------------------------------------");
// for (int i = 0; i < tokens.length ; i++)
// {
// // System.out.println( "[" + tokens[i] + "]");
// }
// // System.out.println( "------------------------------------------");
// }
}//end of class Tokenizer