From ce97e928ad890631e80257b4ea647cb9ca47d44a Mon Sep 17 00:00:00 2001 From: BWS Systems Date: Mon, 31 Dec 2018 14:06:48 -0600 Subject: [PATCH] Updated harmony hub disconnect handling --- pom.xml | 2 +- .../plugins/harmony/HarmonyHandler.java | 49 ++-- .../HABridge/plugins/harmony/HarmonyHome.java | 273 +++++++++++------- .../plugins/harmony/HarmonyServer.java | 8 +- 4 files changed, 205 insertions(+), 127 deletions(-) diff --git a/pom.xml b/pom.xml index eca2fd7..9141efc 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 5.2.2RC2 + 5.2.2RC3 jar HA Bridge diff --git a/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyHandler.java b/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyHandler.java index 6cfb3d3..bcb0f1e 100644 --- a/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyHandler.java +++ b/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyHandler.java @@ -43,6 +43,7 @@ public class HarmonyHandler { listOfActivities = harmonyClient.getConfig().getActivities(); } catch (RuntimeException e) { handleExceptionError(e); + return null; } return listOfActivities; @@ -59,6 +60,7 @@ public class HarmonyHandler { listOfDevices = harmonyClient.getConfig().getDevices(); } catch (RuntimeException e) { handleExceptionError(e); + return null; } return listOfDevices; } @@ -73,6 +75,7 @@ public class HarmonyHandler { aConfig = harmonyClient.getConfig(); } catch (RuntimeException e) { handleExceptionError(e); + return null; } return aConfig; } @@ -87,6 +90,7 @@ public class HarmonyHandler { anActivity = harmonyClient.getCurrentActivity(); } catch (RuntimeException e) { handleExceptionError(e); + return null; } return anActivity; } @@ -112,16 +116,14 @@ public class HarmonyHandler { harmonyClient.startActivityByName(anActivity.getName()); } catch (IllegalArgumentException ei) { log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub()); - return false; } catch (RuntimeException e1) { - handleExceptionError(e1); + return handleExceptionError(e1); } } catch (RuntimeException e1) { - handleExceptionError(e1); + return handleExceptionError(e1); } } else { log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub()); - return false; } return true; @@ -147,40 +149,45 @@ public class HarmonyHandler { harmonyClient.pressButton(aDeviceButton.getDevice(), aDeviceButton.getButton()); } 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); + return handleExceptionError(e1); } } catch (RuntimeException e1) { - handleExceptionError(e1); + return handleExceptionError(e1); } } else { log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub()); + } + + return true; + } + + boolean handleExceptionError(Exception e) { + if(e.getMessage().equalsIgnoreCase("Failed communicating with Harmony Hub")) { + log.warn("Issue in communcicating with Harmony Hub, retrying connect...."); return false; } 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) return; - - harmonyClient.disconnect(); + try { + harmonyClient.disconnect(); + } catch(Exception e) + { + // noop + } harmonyClient = null; } + /** + * @return the myNameAndIP + */ + public NamedIP getMyNameAndIP() { + return myNameAndIP; + } } diff --git a/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyHome.java b/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyHome.java index 05ee46b..90cdc87 100644 --- a/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyHome.java +++ b/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyHome.java @@ -27,7 +27,7 @@ import net.whistlingfish.harmony.config.Activity; import net.whistlingfish.harmony.config.Device; public class HarmonyHome implements Home { - private static final Logger log = LoggerFactory.getLogger(HarmonyHome.class); + private static final Logger log = LoggerFactory.getLogger(HarmonyHome.class); private Map hubs; private Boolean isDevMode; private Boolean validHarmony; @@ -43,91 +43,118 @@ public class HarmonyHome implements Home { @Override public void closeHome() { - if(!validHarmony) + if (!validHarmony) return; log.debug("Closing Home."); - if(closed) { + if (closed) { log.debug("Home is already closed...."); return; } - if(isDevMode || hubs == null) + if (isDevMode || hubs == null) return; Iterator keys = hubs.keySet().iterator(); - while(keys.hasNext()) { + while (keys.hasNext()) { String key = keys.next(); hubs.get(key).getMyHarmony().shutdown(); } - + hubs = null; closed = true; } public HarmonyHandler getHarmonyHandler(String aName) { - if(!validHarmony) + if (!validHarmony) return null; HarmonyHandler aHandler = null; - if(aName == null || aName.equals("")) { + if (aName == null || aName.equals("")) { aName = "default"; } - if(hubs.get(aName) == null) { + if (hubs.get(aName) == null) { Set keys = hubs.keySet(); - if(!keys.isEmpty()) { + if (!keys.isEmpty()) { aHandler = hubs.get(keys.toArray()[0]).getMyHarmony(); - } - else + } else aHandler = null; - } - else + } else aHandler = hubs.get(aName).getMyHarmony(); return aHandler; } - + public List getActivities() { Iterator keys = hubs.keySet().iterator(); ArrayList activityList = new ArrayList(); - if(!validHarmony) + if (!validHarmony) return null; - while(keys.hasNext()) { + while (keys.hasNext()) { String key = keys.next(); Iterator activities = hubs.get(key).getMyHarmony().getActivities().iterator(); - while(activities.hasNext()) { + if (activities == null) { + resetHub(hubs.get(key).getMyHarmony()); + activities = hubs.get(key).getMyHarmony().getActivities().iterator(); + if (activities == null) { + log.error("Could not get communication restored with hub: " + key + ", please restart..."); + } + } + if (activities != null) { + while (activities.hasNext()) { + HarmonyActivity anActivity = new HarmonyActivity(); + anActivity.setActivity(activities.next()); + anActivity.setHub(key); + activityList.add(anActivity); + } + } + } + return activityList; + } + + public List getCurrentActivities() { + Iterator keys = hubs.keySet().iterator(); + ArrayList activityList = new ArrayList(); + if (!validHarmony) + return null; + while (keys.hasNext()) { + String key = keys.next(); + Activity theActivity = hubs.get(key).getMyHarmony().getCurrentActivity(); + if (theActivity == null) { + resetHub(hubs.get(key).getMyHarmony()); + theActivity = hubs.get(key).getMyHarmony().getCurrentActivity(); + if (theActivity == null) { + log.error("Could not get communication restored with hub: " + key + ", please restart..."); + } + } + if (theActivity != null) { HarmonyActivity anActivity = new HarmonyActivity(); - anActivity.setActivity(activities.next()); + anActivity.setActivity(theActivity); anActivity.setHub(key); activityList.add(anActivity); } } return activityList; } - public List getCurrentActivities() { - Iterator keys = hubs.keySet().iterator(); - ArrayList activityList = new ArrayList(); - if(!validHarmony) - return null; - while(keys.hasNext()) { - String key = keys.next(); - Activity theActivity = hubs.get(key).getMyHarmony().getCurrentActivity(); - HarmonyActivity anActivity = new HarmonyActivity(); - anActivity.setActivity(theActivity); - anActivity.setHub(key); - activityList.add(anActivity); - } - return activityList; - } + public List getDevices() { Iterator keys = hubs.keySet().iterator(); ArrayList deviceList = new ArrayList(); - if(!validHarmony) + if (!validHarmony) return null; - while(keys.hasNext()) { + while (keys.hasNext()) { String key = keys.next(); Iterator devices = hubs.get(key).getMyHarmony().getDevices().iterator(); - while(devices.hasNext()) { - HarmonyDevice aDevice = new HarmonyDevice(); - aDevice.setDevice(devices.next()); - aDevice.setHub(key); - deviceList.add(aDevice); + if (devices == null) { + resetHub(hubs.get(key).getMyHarmony()); + devices = hubs.get(key).getMyHarmony().getDevices().iterator(); + if (devices == null) { + log.error("Could not get communication restored with hub: " + key + ", please restart..."); + } + } + if (devices != null) { + while (devices.hasNext()) { + HarmonyDevice aDevice = new HarmonyDevice(); + aDevice.setDevice(devices.next()); + aDevice.setHub(key); + deviceList.add(aDevice); + } } } return deviceList; @@ -135,23 +162,22 @@ public class HarmonyHome implements Home { @Override public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, - Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) { + Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) { String responseString = null; log.debug("executing HUE api request to change " + anItem.getType() + " to Harmony: " + device.getName()); - if(!validHarmony) { + if (!validHarmony) { log.warn("Should not get here, no harmony configured"); responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + "\",\"description\": \"Should not get here, no harmony configured\", \"parameter\": \"/lights/" - + lightId + "state\"}}]"; + + lightId + "state\"}}]"; } else { - if(anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.HARMONY_ACTIVITY[DeviceMapTypes.typeIndex])) - { + if (anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.HARMONY_ACTIVITY[DeviceMapTypes.typeIndex])) { RunActivity anActivity = null; - if(anItem.getItem().isJsonObject()) + if (anItem.getItem().isJsonObject()) anActivity = aGsonHandler.fromJson(anItem.getItem(), RunActivity.class); else anActivity = aGsonHandler.fromJson(anItem.getItem().getAsString(), RunActivity.class); - if(anActivity.getHub() == null || anActivity.getHub().isEmpty()) + if (anActivity.getHub() == null || anActivity.getHub().isEmpty()) anActivity.setHub(device.getTargetDevice()); HarmonyHandler myHarmony = getHarmonyHandler(anActivity.getHub()); if (myHarmony == null) { @@ -160,11 +186,23 @@ public class HarmonyHome implements Home { + "\",\"description\": \"Should not get here, no harmony hub available\", \"parameter\": \"/lights/" + lightId + "state\"}}]"; } else { - myHarmony.startActivity(anActivity); + if (!myHarmony.startActivity(anActivity)) { + if (resetHub(myHarmony)) { + myHarmony = getHarmonyHandler(anActivity.getHub()); + if (!myHarmony.startActivity(anActivity)) { + log.error("Could not get communication restored with hub: " + anActivity.getHub() + + ", please restart..."); + responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + + "\",\"description\": \"Could not communicate with harmony\", \"parameter\": \"/lights/" + + lightId + "state\"}}]"; + } + } + } } - } else if(anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.HARMONY_BUTTON[DeviceMapTypes.typeIndex])) { + } else if (anItem.getType().trim() + .equalsIgnoreCase(DeviceMapTypes.HARMONY_BUTTON[DeviceMapTypes.typeIndex])) { String url = null; - if(anItem.getItem().isJsonObject() || anItem.getItem().isJsonArray()) { + if (anItem.getItem().isJsonObject() || anItem.getItem().isJsonArray()) { url = aGsonHandler.toJson(anItem.getItem()); } else url = anItem.getItem().getAsString(); @@ -172,35 +210,50 @@ public class HarmonyHome implements Home { if (url.substring(0, 1).equalsIgnoreCase("{")) { url = "[" + url + "]"; } - + url = BrightnessDecode.calculateReplaceIntensityValue(url, intensity, targetBri, targetBriInc, false); ButtonPress[] deviceButtons = aGsonHandler.fromJson(url, ButtonPress[].class); - Integer theCount = 1; - for(int z = 0; z < deviceButtons.length; z++) { - if(deviceButtons[z].getCount() != null && deviceButtons[z].getCount() > 0) - theCount = deviceButtons[z].getCount(); - for(int y = 0; y < theCount; y++) { - if( y > 0 || z > 0) { - try { - Thread.sleep(aMultiUtil.getTheDelay()); - } catch (InterruptedException e) { - // ignore + Integer theCount = 1; + for (int z = 0; z < deviceButtons.length; z++) { + if (deviceButtons[z].getCount() != null && deviceButtons[z].getCount() > 0) + theCount = deviceButtons[z].getCount(); + for (int y = 0; y < theCount; y++) { + if (y > 0 || z > 0) { + try { + Thread.sleep(aMultiUtil.getTheDelay()); + } catch (InterruptedException e) { + // ignore + } + } + if (anItem.getDelay() != null && anItem.getDelay() > 0) + aMultiUtil.setTheDelay(anItem.getDelay()); + else + aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault()); + log.debug("pressing button: " + deviceButtons[z].getDevice() + " - " + + deviceButtons[z].getButton() + " with pressTime of: " + + deviceButtons[z].getPressTime() + " - iteration: " + String.valueOf(z) + " - count: " + + String.valueOf(y)); + if (deviceButtons[z].getHub() == null || deviceButtons[z].getHub().isEmpty()) + deviceButtons[z].setHub(device.getTargetDevice()); + HarmonyHandler myHarmony = getHarmonyHandler(deviceButtons[z].getHub()); + if (myHarmony == null) + log.warn("Button Press - Should not get here, no harmony hub available"); + else{ + if (myHarmony.pressButton(deviceButtons[z])) { + if (resetHub(myHarmony)) { + myHarmony = getHarmonyHandler(deviceButtons[z].getHub()); + if (!myHarmony.pressButton(deviceButtons[z])) { + log.error("Could not get communication restored with hub: " + deviceButtons[z].getHub() + + ", please restart..."); + responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + + "\",\"description\": \"Could not communicate with harmony\", \"parameter\": \"/lights/" + + lightId + "state\"}}]"; + } } } - if (anItem.getDelay() != null && anItem.getDelay() > 0) - aMultiUtil.setTheDelay(anItem.getDelay()); - else - aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault()); - log.debug("pressing button: " + deviceButtons[z].getDevice() + " - " + deviceButtons[z].getButton() + " with pressTime of: " + deviceButtons[z].getPressTime() + " - iteration: " + String.valueOf(z) + " - count: " + String.valueOf(y)); - if(deviceButtons[z].getHub() == null || deviceButtons[z].getHub().isEmpty()) - deviceButtons[z].setHub(device.getTargetDevice()); - HarmonyHandler myHarmony = getHarmonyHandler(deviceButtons[z].getHub()); - if (myHarmony == null) - log.warn("Button Press - Should not get here, no harmony hub available"); - else - myHarmony.pressButton(deviceButtons[z]); - } - } + } + } + } } } return responseString; @@ -208,15 +261,14 @@ public class HarmonyHome implements Home { @Override public Home createHome(BridgeSettings bridgeSettings) { - isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false")); - validHarmony = bridgeSettings.getBridgeSettingsDescriptor().isValidHarmony(); - log.info("Harmony Home created." + (validHarmony ? "" : " No Harmony devices configured.") + (isDevMode ? " DevMode is set." : "")); - if(validHarmony || isDevMode) { + isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false")); + validHarmony = bridgeSettings.getBridgeSettingsDescriptor().isValidHarmony(); + log.info("Harmony Home created." + (validHarmony ? "" : " No Harmony devices configured.") + + (isDevMode ? " DevMode is set." : "")); + if (validHarmony || isDevMode) { hubs = new HashMap(); - aGsonHandler = - new GsonBuilder() - .create(); - if(isDevMode) { + aGsonHandler = new GsonBuilder().create(); + if (isDevMode) { NamedIP devModeIp = new NamedIP(); devModeIp.setIp("10.10.10.10"); devModeIp.setName("devMode"); @@ -226,19 +278,21 @@ public class HarmonyHome implements Home { thedevList.setDevices(theList); bridgeSettings.getBridgeSettingsDescriptor().setHarmonyAddress(thedevList); } - Iterator theList = bridgeSettings.getBridgeSettingsDescriptor().getHarmonyAddress().getDevices().iterator(); - while(theList.hasNext() && validHarmony) { + Iterator theList = bridgeSettings.getBridgeSettingsDescriptor().getHarmonyAddress().getDevices() + .iterator(); + while (theList.hasNext() && validHarmony) { NamedIP aHub = theList.next(); boolean loopControl = true; int retryCount = 0; - while(loopControl) { + while (loopControl) { try { - hubs.put(aHub.getName(), HarmonyServer.setup(bridgeSettings.getBridgeSettingsDescriptor(), isDevMode, aHub)); - loopControl = false; + hubs.put(aHub.getName(), HarmonyServer.setup(isDevMode, aHub)); + loopControl = false; } catch (Exception e) { - if(retryCount > 3) { - log.error("Cannot get harmony client (" + aHub.getName() + ") setup, Exiting with message: " + e.getMessage(), e); - loopControl = false; + if (retryCount > 3) { + log.error("Cannot get harmony client (" + aHub.getName() + ") setup, Exiting with message: " + + e.getMessage(), e); + loopControl = false; } else { try { Thread.sleep(2000); @@ -246,25 +300,44 @@ public class HarmonyHome implements Home { // ignore } } - + retryCount++; } } } - if(hubs.isEmpty()) + if (hubs.isEmpty()) validHarmony = false; } return this; } + private boolean resetHub(HarmonyHandler aHarmony) { + boolean resetSuccess = false; + isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false")); + NamedIP resetIp = aHarmony.getMyNameAndIP(); + log.info("Resetting harmony hub due to communication errror: " + resetIp.getName()); + if (!isDevMode) { + try { + hubs.remove(resetIp.getName()); + aHarmony.shutdown(); + hubs.put(resetIp.getName(), HarmonyServer.setup(isDevMode, resetIp)); + resetSuccess = true; + } catch (Exception e) { + log.error("Cannot reset harmony client (" + resetIp.getName() + "), Exiting with message: " + + e.getMessage(), e); + } + } + return resetSuccess; + } + @Override public Object getItems(String type) { - if(validHarmony) { - if(type.equalsIgnoreCase(DeviceMapTypes.HARMONY_ACTIVITY[DeviceMapTypes.typeIndex])) + if (validHarmony) { + if (type.equalsIgnoreCase(DeviceMapTypes.HARMONY_ACTIVITY[DeviceMapTypes.typeIndex])) return getActivities(); - if(type.equalsIgnoreCase(DeviceMapTypes.HARMONY_BUTTON[DeviceMapTypes.typeIndex])) + if (type.equalsIgnoreCase(DeviceMapTypes.HARMONY_BUTTON[DeviceMapTypes.typeIndex])) return getDevices(); - if(type.equalsIgnoreCase("current_activity")) + if (type.equalsIgnoreCase("current_activity")) return getCurrentActivities(); } return null; @@ -272,7 +345,7 @@ public class HarmonyHome implements Home { @Override public void refresh() { - // noop + // noop } - + } diff --git a/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyServer.java b/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyServer.java index f7b7c9e..e24f60a 100644 --- a/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyServer.java +++ b/src/main/java/com/bwssystems/HABridge/plugins/harmony/HarmonyServer.java @@ -11,7 +11,6 @@ import org.apache.http.client.methods.HttpGet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.bwssystems.HABridge.BridgeSettingsDescriptor; import com.bwssystems.HABridge.NamedIP; import com.google.inject.Guice; import com.google.inject.Injector; @@ -50,11 +49,10 @@ public class HarmonyServer { } public static HarmonyServer setup( - BridgeSettingsDescriptor bridgeSettings, Boolean harmonyDevMode, NamedIP theHarmonyAddress ) throws Exception { - if (!bridgeSettings.isValidHarmony() && harmonyDevMode) { + if (harmonyDevMode) { return new HarmonyServer(theHarmonyAddress); } Injector injector = null; @@ -65,11 +63,11 @@ public class HarmonyServer { if (!harmonyDevMode) { injector.injectMembers(mainObject); } - mainObject.execute(bridgeSettings, harmonyDevMode); + mainObject.execute(harmonyDevMode); return mainObject; } - private void execute(BridgeSettingsDescriptor mySettings, Boolean harmonyDevMode) throws Exception { + private void execute(Boolean harmonyDevMode) throws Exception { Boolean noopCalls = Boolean.parseBoolean(System.getProperty("noop.calls", "false")); isDevMode = harmonyDevMode; String modeString = "";