mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-16 18:24:36 +00:00
Added new HTTP pool manager and http handling.
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<groupId>com.bwssystems.HABridge</groupId>
|
<groupId>com.bwssystems.HABridge</groupId>
|
||||||
<artifactId>ha-bridge</artifactId>
|
<artifactId>ha-bridge</artifactId>
|
||||||
<version>5.0.0rc3</version>
|
<version>5.0.0rc4</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>HA Bridge</name>
|
<name>HA Bridge</name>
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ public class HABridge {
|
|||||||
bridgeSettings.getBridgeControl().setStop(true);
|
bridgeSettings.getBridgeControl().setStop(true);
|
||||||
if(bridgeSettings.getBridgeSettingsDescriptor().isSettingsChanged())
|
if(bridgeSettings.getBridgeSettingsDescriptor().isSettingsChanged())
|
||||||
bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor());
|
bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor());
|
||||||
|
log.info("Going to close all homes");
|
||||||
homeManager.closeHomes();
|
homeManager.closeHomes();
|
||||||
udpSender.closeResponseSocket();
|
udpSender.closeResponseSocket();
|
||||||
udpSender = null;
|
udpSender = null;
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import java.util.Collection;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.bwssystems.HABridge.devicemanagmeent.ResourceHandler;
|
import com.bwssystems.HABridge.devicemanagmeent.ResourceHandler;
|
||||||
import com.bwssystems.HABridge.plugins.NestBridge.NestHome;
|
import com.bwssystems.HABridge.plugins.NestBridge.NestHome;
|
||||||
import com.bwssystems.HABridge.plugins.domoticz.DomoticzHome;
|
import com.bwssystems.HABridge.plugins.domoticz.DomoticzHome;
|
||||||
@@ -23,6 +26,7 @@ import com.bwssystems.HABridge.plugins.fibaro.FibaroHome;
|
|||||||
import com.bwssystems.HABridge.util.UDPDatagramSender;
|
import com.bwssystems.HABridge.util.UDPDatagramSender;
|
||||||
|
|
||||||
public class HomeManager {
|
public class HomeManager {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(HomeManager.class);
|
||||||
Map<String, Home> homeList;
|
Map<String, Home> homeList;
|
||||||
Map<String, Home> resourceList;
|
Map<String, Home> resourceList;
|
||||||
|
|
||||||
@@ -114,8 +118,10 @@ public class HomeManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void closeHomes() {
|
public void closeHomes() {
|
||||||
|
log.info("Manager close homes called....");
|
||||||
Collection<Home> theHomes = homeList.values();
|
Collection<Home> theHomes = homeList.values();
|
||||||
for(Home aHome : theHomes) {
|
for(Home aHome : theHomes) {
|
||||||
|
log.info("Closing home: " + aHome.getClass().getCanonicalName());
|
||||||
aHome.closeHome();
|
aHome.closeHome();
|
||||||
}
|
}
|
||||||
homeList.clear();
|
homeList.clear();
|
||||||
|
|||||||
@@ -32,10 +32,13 @@ public class NestHome implements com.bwssystems.HABridge.Home {
|
|||||||
private Gson aGsonHandler;
|
private Gson aGsonHandler;
|
||||||
private Boolean isFarenheit;
|
private Boolean isFarenheit;
|
||||||
private Boolean validNest;
|
private Boolean validNest;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public NestHome(BridgeSettings bridgeSettings) {
|
public NestHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -93,12 +96,18 @@ public class NestHome implements com.bwssystems.HABridge.Home {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(theSession != null) {
|
if(theSession != null) {
|
||||||
theNest.endNestSession();
|
theNest.endNestSession();
|
||||||
}
|
}
|
||||||
theNest = null;
|
theNest = null;
|
||||||
theSession = null;
|
theSession = null;
|
||||||
nestItems = null;
|
nestItems = null;
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -27,10 +27,13 @@ public class DomoticzHome implements Home {
|
|||||||
private Map<String, DomoticzHandler> domoticzs;
|
private Map<String, DomoticzHandler> domoticzs;
|
||||||
private Boolean validDomoticz;
|
private Boolean validDomoticz;
|
||||||
private HTTPHandler httpClient;
|
private HTTPHandler httpClient;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public DomoticzHome(BridgeSettings bridgeSettings) {
|
public DomoticzHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -162,8 +165,15 @@ public class DomoticzHome implements Home {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(httpClient != null)
|
if(httpClient != null)
|
||||||
httpClient.closeHandler();
|
httpClient.closeHandler();
|
||||||
|
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,13 @@ import com.bwssystems.HABridge.hue.TimeDecode;
|
|||||||
public class CommandHome implements Home {
|
public class CommandHome implements Home {
|
||||||
private static final Logger log = LoggerFactory.getLogger(CommandHome.class);
|
private static final Logger log = LoggerFactory.getLogger(CommandHome.class);
|
||||||
private BridgeSettings theSettings;
|
private BridgeSettings theSettings;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public CommandHome(BridgeSettings bridgeSettings) {
|
public CommandHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -93,8 +96,13 @@ public class CommandHome implements Home {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
// noop
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,11 +25,14 @@ public class FibaroHome implements Home
|
|||||||
private static final Logger log = LoggerFactory.getLogger(FibaroHome.class);
|
private static final Logger log = LoggerFactory.getLogger(FibaroHome.class);
|
||||||
private Map<String, FibaroInfo> fibaros;
|
private Map<String, FibaroInfo> fibaros;
|
||||||
private Boolean validFibaro;
|
private Boolean validFibaro;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public FibaroHome(BridgeSettings bridgeSettings)
|
public FibaroHome(BridgeSettings bridgeSettings)
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Device> getDevices()
|
public List<Device> getDevices()
|
||||||
@@ -102,6 +105,12 @@ public class FibaroHome implements Home
|
|||||||
@Override
|
@Override
|
||||||
public void closeHome()
|
public void closeHome()
|
||||||
{
|
{
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
fibaros = null;
|
fibaros = null;
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,10 +27,13 @@ public class HalHome implements Home {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(HalHome.class);
|
private static final Logger log = LoggerFactory.getLogger(HalHome.class);
|
||||||
private Map<String, HalInfo> hals;
|
private Map<String, HalInfo> hals;
|
||||||
private Boolean validHal;
|
private Boolean validHal;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public HalHome(BridgeSettings bridgeSettings) {
|
public HalHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -194,7 +197,13 @@ public class HalHome implements Home {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
// noop
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hals = null;
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,16 +32,24 @@ public class HarmonyHome implements Home {
|
|||||||
private Boolean isDevMode;
|
private Boolean isDevMode;
|
||||||
private Boolean validHarmony;
|
private Boolean validHarmony;
|
||||||
private Gson aGsonHandler;
|
private Gson aGsonHandler;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public HarmonyHome(BridgeSettings bridgeSettings) {
|
public HarmonyHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
if(!validHarmony)
|
if(!validHarmony)
|
||||||
return;
|
return;
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(isDevMode || hubs == null)
|
if(isDevMode || hubs == null)
|
||||||
return;
|
return;
|
||||||
Iterator<String> keys = hubs.keySet().iterator();
|
Iterator<String> keys = hubs.keySet().iterator();
|
||||||
@@ -51,6 +59,7 @@ public class HarmonyHome implements Home {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hubs = null;
|
hubs = null;
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HarmonyHandler getHarmonyHandler(String aName) {
|
public HarmonyHandler getHarmonyHandler(String aName) {
|
||||||
|
|||||||
@@ -26,10 +26,13 @@ public class HassHome implements Home {
|
|||||||
private Map<String, HomeAssistant> hassMap;
|
private Map<String, HomeAssistant> hassMap;
|
||||||
private Boolean validHass;
|
private Boolean validHass;
|
||||||
private Gson aGsonHandler;
|
private Gson aGsonHandler;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public HassHome(BridgeSettings bridgeSettings) {
|
public HassHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -152,6 +155,11 @@ public class HassHome implements Home {
|
|||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
if(!validHass)
|
if(!validHass)
|
||||||
return;
|
return;
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(hassMap == null)
|
if(hassMap == null)
|
||||||
return;
|
return;
|
||||||
Iterator<String> keys = hassMap.keySet().iterator();
|
Iterator<String> keys = hassMap.keySet().iterator();
|
||||||
@@ -161,5 +169,6 @@ public class HassHome implements Home {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hassMap = null;
|
hassMap = null;
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,28 +4,15 @@ import java.io.IOException;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.http.HttpClientConnection;
|
|
||||||
import org.apache.http.HttpException;
|
|
||||||
import org.apache.http.HttpHost;
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.client.ClientProtocolException;
|
import org.apache.http.client.ClientProtocolException;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.client.methods.HttpPut;
|
import org.apache.http.client.methods.HttpPut;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.client.protocol.HttpClientContext;
|
|
||||||
import org.apache.http.conn.ConnectionPoolTimeoutException;
|
|
||||||
import org.apache.http.conn.ConnectionRequest;
|
|
||||||
import org.apache.http.conn.HttpClientConnectionManager;
|
|
||||||
import org.apache.http.conn.routing.HttpRoute;
|
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
|
||||||
import org.apache.http.protocol.HttpRequestExecutor;
|
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -34,29 +21,9 @@ import com.bwssystems.HABridge.api.NameValue;
|
|||||||
|
|
||||||
public class HTTPHandler {
|
public class HTTPHandler {
|
||||||
private static final Logger log = LoggerFactory.getLogger(HTTPHandler.class);
|
private static final Logger log = LoggerFactory.getLogger(HTTPHandler.class);
|
||||||
// private CloseableHttpClient httpClient;
|
|
||||||
// private RequestConfig globalConfig;
|
|
||||||
private HttpClientContext context;
|
|
||||||
private PoolingHttpClientConnectionManager connMgr;
|
|
||||||
private HttpRoute route;
|
|
||||||
private HttpClientConnection conn;
|
|
||||||
private HttpHost theHost;
|
|
||||||
|
|
||||||
public HTTPHandler() {
|
public HTTPHandler() {
|
||||||
context = HttpClientContext.create();
|
super();
|
||||||
connMgr = new PoolingHttpClientConnectionManager();
|
|
||||||
// Increase max total connection to 200
|
|
||||||
connMgr.setMaxTotal(200);
|
|
||||||
// Increase default max connection per route to 20
|
|
||||||
connMgr.setDefaultMaxPerRoute(20);
|
|
||||||
// Increase max connections for localhost:80 to 50
|
|
||||||
HttpHost localhost = new HttpHost("locahost", 80);
|
|
||||||
connMgr.setMaxPerRoute(new HttpRoute(localhost), 50);
|
|
||||||
route = null;
|
|
||||||
conn = null;
|
|
||||||
theHost = null;
|
|
||||||
// globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
|
|
||||||
// httpClient = HttpClients.custom().setDefaultRequestConfig(globalConfig).build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -68,9 +35,8 @@ public class HTTPHandler {
|
|||||||
String theContent = null;
|
String theContent = null;
|
||||||
URI theURI = null;
|
URI theURI = null;
|
||||||
ContentType parsedContentType = null;
|
ContentType parsedContentType = null;
|
||||||
ConnectionRequest connRequest = null;
|
|
||||||
StringEntity requestBody = null;
|
StringEntity requestBody = null;
|
||||||
boolean badResponse = false;
|
|
||||||
if (contentType != null && !contentType.trim().isEmpty()) {
|
if (contentType != null && !contentType.trim().isEmpty()) {
|
||||||
parsedContentType = ContentType.parse(contentType);
|
parsedContentType = ContentType.parse(contentType);
|
||||||
if (body != null && body.length() > 0)
|
if (body != null && body.length() > 0)
|
||||||
@@ -82,44 +48,7 @@ public class HTTPHandler {
|
|||||||
log.warn("Error creating URI http request: " + url + " with message: " + e1.getMessage());
|
log.warn("Error creating URI http request: " + url + " with message: " + e1.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if(route == null) {
|
|
||||||
theHost = new HttpHost(theURI.getHost(), theURI.getPort());
|
|
||||||
route = new HttpRoute(theHost);
|
|
||||||
}
|
|
||||||
if(conn == null) {
|
|
||||||
// Request new connection. This can be a long process
|
|
||||||
connRequest = connMgr.requestConnection(route, null);
|
|
||||||
// Wait for connection up to 10 sec
|
|
||||||
try {
|
|
||||||
conn = connRequest.get(10, TimeUnit.SECONDS);
|
|
||||||
} catch (ConnectionPoolTimeoutException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If not open
|
|
||||||
if (!conn.isOpen()) {
|
|
||||||
// establish connection based on its route info
|
|
||||||
try {
|
|
||||||
connMgr.connect(conn, route, 1000, context);
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
// and mark it as route complete
|
|
||||||
try {
|
|
||||||
connMgr.routeComplete(conn, route, context);
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
if (httpVerb == null || httpVerb.trim().isEmpty() || HttpGet.METHOD_NAME.equalsIgnoreCase(httpVerb)) {
|
if (httpVerb == null || httpVerb.trim().isEmpty() || HttpGet.METHOD_NAME.equalsIgnoreCase(httpVerb)) {
|
||||||
request = new HttpGet(theURI);
|
request = new HttpGet(theURI);
|
||||||
@@ -146,28 +75,12 @@ public class HTTPHandler {
|
|||||||
request.setHeader(headers[i].getName(), headers[i].getValue());
|
request.setHeader(headers[i].getName(), headers[i].getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HttpResponse response = null;
|
CloseableHttpResponse response = null;
|
||||||
HttpRequestExecutor exeRequest = new HttpRequestExecutor();
|
|
||||||
context.setTargetHost(theHost);
|
|
||||||
for (int retryCount = 0; retryCount < 2; retryCount++) {
|
for (int retryCount = 0; retryCount < 2; retryCount++) {
|
||||||
try {
|
try {
|
||||||
response = exeRequest.execute(request, conn, context);
|
response = HttpClientPool.getClient().execute(request);
|
||||||
log.debug((httpVerb == null ? "GET" : httpVerb) + " execute (" + retryCount + ") on URL responded: "
|
log.debug((httpVerb == null ? "GET" : httpVerb) + " execute (" + retryCount + ") on URL responded: "
|
||||||
+ response.getStatusLine().getStatusCode());
|
+ response.getStatusLine().getStatusCode());
|
||||||
if (response != null && response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
|
|
||||||
log.debug("Successfull response - The http response is <<<" + theContent + ">>>");
|
|
||||||
retryCount = 2;
|
|
||||||
} else if (response != null) {
|
|
||||||
log.warn("HTTP response code was not an expected successful response of between 200 - 299, the code was: "
|
|
||||||
+ response.getStatusLine());
|
|
||||||
if (response.getStatusLine().getStatusCode() == 504) {
|
|
||||||
log.warn("HTTP response code was 504, retrying...");
|
|
||||||
} else
|
|
||||||
retryCount = 2;
|
|
||||||
|
|
||||||
badResponse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response != null && response.getEntity() != null) {
|
if (response != null && response.getEntity() != null) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@@ -180,18 +93,28 @@ public class HTTPHandler {
|
|||||||
// inputstream
|
// inputstream
|
||||||
// ignore
|
// ignore
|
||||||
// content
|
// content
|
||||||
if(!badResponse)
|
|
||||||
theContent = null;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.debug("Error ocurred in handling response entity after successful call, still responding success. "
|
log.debug("Error ocurred in handling response entity after successful call, still responding success. "
|
||||||
+ e.getMessage(), e);
|
+ e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (response != null && response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
|
||||||
|
log.debug("Successfull response - The http response is <<<" + theContent + ">>>");
|
||||||
|
retryCount = 2;
|
||||||
|
} else if (response != null) {
|
||||||
|
log.warn("HTTP response code was not an expected successful response of between 200 - 299, the code was: "
|
||||||
|
+ response.getStatusLine());
|
||||||
|
if (response.getStatusLine().getStatusCode() == 504) {
|
||||||
|
log.warn("HTTP response code was 504, retrying...");
|
||||||
|
} else
|
||||||
|
retryCount = 2;
|
||||||
|
|
||||||
|
theContent = null;
|
||||||
|
}
|
||||||
|
|
||||||
} catch (ClientProtocolException e) {
|
} catch (ClientProtocolException e) {
|
||||||
log.warn("Client Protocol Exception received, retyring....");
|
log.warn("Client Protocol Exception received, retyring....");
|
||||||
} catch (HttpException e) {
|
}catch (IOException e) {
|
||||||
log.warn("Error calling out to HA gateway: HttpException in log", e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Error calling out to HA gateway: IOException in log: " + e.getMessage());
|
log.warn("Error calling out to HA gateway: IOException in log: " + e.getMessage());
|
||||||
retryCount = 2;
|
retryCount = 2;
|
||||||
}
|
}
|
||||||
@@ -205,30 +128,8 @@ public class HTTPHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
connMgr.releaseConnection(conn, null, 1, TimeUnit.SECONDS);
|
|
||||||
return theContent;
|
return theContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public HttpClient getHttpClient() {
|
|
||||||
// return httpClient;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// public CloseableHttpClient getHttpClient() {
|
|
||||||
// return httpClient;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
public void closeHandler() {
|
public void closeHandler() {
|
||||||
try {
|
|
||||||
// httpClient.close();
|
|
||||||
if(conn != null)
|
|
||||||
conn.close();
|
|
||||||
connMgr.closeExpiredConnections();
|
|
||||||
connMgr.shutdown();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
// httpClient = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.bwssystems.HABridge.plugins.http;
|
package com.bwssystems.HABridge.plugins.http;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -21,10 +23,15 @@ import com.google.gson.Gson;
|
|||||||
public class HTTPHome implements Home {
|
public class HTTPHome implements Home {
|
||||||
private static final Logger log = LoggerFactory.getLogger(HTTPHome.class);
|
private static final Logger log = LoggerFactory.getLogger(HTTPHome.class);
|
||||||
private HTTPHandler anHttpHandler;
|
private HTTPHandler anHttpHandler;
|
||||||
|
protected HttpClientPool thePool;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public HTTPHome(BridgeSettings bridgeSettings) {
|
public HTTPHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
|
thePool = new HttpClientPool();
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -101,9 +108,22 @@ public class HTTPHome implements Home {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(anHttpHandler != null)
|
if(anHttpHandler != null)
|
||||||
anHttpHandler.closeHandler();
|
anHttpHandler.closeHandler();
|
||||||
anHttpHandler = null;
|
anHttpHandler = null;
|
||||||
|
try {
|
||||||
|
HttpClientPool.shutdown();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.warn("Error shutting down http pool: " + e.getMessage());;
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("Error shutting down http pool: " + e.getMessage());;
|
||||||
|
}
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
package com.bwssystems.HABridge.plugins.http;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public final class HttpClientPool {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(HttpClientPool.class);
|
||||||
|
|
||||||
|
// Single-element enum to implement Singleton.
|
||||||
|
private static enum Singleton {
|
||||||
|
// Just one of me so constructor will be called once.
|
||||||
|
Client;
|
||||||
|
// The thread-safe client.
|
||||||
|
private final CloseableHttpClient threadSafeClient;
|
||||||
|
// The pool monitor.
|
||||||
|
private final IdleConnectionMonitorThread monitor;
|
||||||
|
|
||||||
|
// The constructor creates it - thus late
|
||||||
|
private Singleton() {
|
||||||
|
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
|
||||||
|
// Increase max total connection to 200
|
||||||
|
cm.setMaxTotal(200);
|
||||||
|
// Increase default max connection per route to 20
|
||||||
|
cm.setDefaultMaxPerRoute(20);
|
||||||
|
// Build the client.
|
||||||
|
threadSafeClient = HttpClients.custom()
|
||||||
|
.setConnectionManager(cm)
|
||||||
|
.build();
|
||||||
|
// Start up an eviction thread.
|
||||||
|
monitor = new IdleConnectionMonitorThread(cm);
|
||||||
|
// Don't stop quitting.
|
||||||
|
monitor.setDaemon(true);
|
||||||
|
monitor.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CloseableHttpClient get() {
|
||||||
|
return threadSafeClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CloseableHttpClient getClient() {
|
||||||
|
// The thread safe client is held by the singleton.
|
||||||
|
return Singleton.Client.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watches for stale connections and evicts them.
|
||||||
|
private static class IdleConnectionMonitorThread extends Thread {
|
||||||
|
// The manager to watch.
|
||||||
|
private final PoolingHttpClientConnectionManager cm;
|
||||||
|
// Use a BlockingQueue to stop everything.
|
||||||
|
private final BlockingQueue<Stop> stopSignal = new ArrayBlockingQueue<Stop>(1);
|
||||||
|
|
||||||
|
// Pushed up the queue.
|
||||||
|
private static class Stop {
|
||||||
|
// The return queue.
|
||||||
|
private final BlockingQueue<Stop> stop = new ArrayBlockingQueue<Stop>(1);
|
||||||
|
|
||||||
|
// Called by the process that is being told to stop.
|
||||||
|
public void stopped() {
|
||||||
|
// Push me back up the queue to indicate we are now stopped.
|
||||||
|
stop.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by the process requesting the stop.
|
||||||
|
public void waitForStopped() throws InterruptedException {
|
||||||
|
// Wait until the callee acknowledges that it has stopped.
|
||||||
|
stop.take();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IdleConnectionMonitorThread(PoolingHttpClientConnectionManager cm) {
|
||||||
|
super();
|
||||||
|
this.cm = cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
// Holds the stop request that stopped the process.
|
||||||
|
Stop stopRequest;
|
||||||
|
// Every 5 seconds.
|
||||||
|
while ((stopRequest = stopSignal.poll(5, TimeUnit.SECONDS)) == null) {
|
||||||
|
// Close expired connections
|
||||||
|
cm.closeExpiredConnections();
|
||||||
|
// Optionally, close connections that have been idle too long.
|
||||||
|
cm.closeIdleConnections(60, TimeUnit.SECONDS);
|
||||||
|
// Look at pool stats.
|
||||||
|
log.debug("Stats: {}", cm.getTotalStats());
|
||||||
|
}
|
||||||
|
// Acknowledge the stop request.
|
||||||
|
stopRequest.stopped();
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
// terminate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() throws InterruptedException, IOException {
|
||||||
|
log.info("Shutting down client pool");
|
||||||
|
// Signal the stop to the thread.
|
||||||
|
Stop stop = new Stop();
|
||||||
|
stopSignal.add(stop);
|
||||||
|
// Wait for the stop to complete.
|
||||||
|
stop.waitForStopped();
|
||||||
|
// Close the pool - Added
|
||||||
|
Singleton.Client.threadSafeClient.close();
|
||||||
|
// Close the connection manager.
|
||||||
|
cm.close();
|
||||||
|
log.info("Client pool shut down");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void shutdown() throws InterruptedException, IOException {
|
||||||
|
// Shutdown the monitor.
|
||||||
|
Singleton.Client.monitor.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,11 +27,14 @@ public class HueHome implements Home {
|
|||||||
private Boolean validHue;
|
private Boolean validHue;
|
||||||
private Gson aGsonHandler;
|
private Gson aGsonHandler;
|
||||||
private BridgeSettings theBridgeSettings;
|
private BridgeSettings theBridgeSettings;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public HueHome(BridgeSettings bridgeSettings) {
|
public HueHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
theBridgeSettings = bridgeSettings;
|
theBridgeSettings = bridgeSettings;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -135,6 +138,11 @@ public class HueHome implements Home {
|
|||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
if(!validHue)
|
if(!validHue)
|
||||||
return;
|
return;
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(hues == null)
|
if(hues == null)
|
||||||
return;
|
return;
|
||||||
Iterator<String> keys = hues.keySet().iterator();
|
Iterator<String> keys = hues.keySet().iterator();
|
||||||
@@ -143,5 +151,6 @@ public class HueHome implements Home {
|
|||||||
hues.get(key).closeHue();;
|
hues.get(key).closeHue();;
|
||||||
}
|
}
|
||||||
hues = null;
|
hues = null;
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,10 +38,13 @@ public class LifxHome implements Home {
|
|||||||
private LFXClient client;
|
private LFXClient client;
|
||||||
private Boolean validLifx;
|
private Boolean validLifx;
|
||||||
private Gson aGsonHandler;
|
private Gson aGsonHandler;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public LifxHome(BridgeSettings bridgeSettings) {
|
public LifxHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -213,7 +216,13 @@ public class LifxHome implements Home {
|
|||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
if(!validLifx)
|
if(!validLifx)
|
||||||
return;
|
return;
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
client.close();
|
client.close();
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
private static class MyLightListener implements LFXLightCollectionListener {
|
private static class MyLightListener implements LFXLightCollectionListener {
|
||||||
private static final Logger log = LoggerFactory.getLogger(MyLightListener.class);
|
private static final Logger log = LoggerFactory.getLogger(MyLightListener.class);
|
||||||
|
|||||||
@@ -26,16 +26,24 @@ public class MQTTHome implements Home {
|
|||||||
private Map<String, MQTTHandler> handlers;
|
private Map<String, MQTTHandler> handlers;
|
||||||
private Boolean validMqtt;
|
private Boolean validMqtt;
|
||||||
private Gson aGsonHandler;
|
private Gson aGsonHandler;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public MQTTHome(BridgeSettings bridgeSettings) {
|
public MQTTHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
if(!validMqtt)
|
if(!validMqtt)
|
||||||
return;
|
return;
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
log.debug("Shutting down MQTT handlers.");
|
log.debug("Shutting down MQTT handlers.");
|
||||||
if(handlers != null && !handlers.isEmpty()) {
|
if(handlers != null && !handlers.isEmpty()) {
|
||||||
for (String key : handlers.keySet()) {
|
for (String key : handlers.keySet()) {
|
||||||
@@ -43,6 +51,7 @@ public class MQTTHome implements Home {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
handlers = null;
|
handlers = null;
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MQTTHandler getMQTTHandler(String aName) {
|
public MQTTHandler getMQTTHandler(String aName) {
|
||||||
|
|||||||
@@ -31,10 +31,13 @@ public class SomfyHome implements Home {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(SomfyHome.class);
|
private static final Logger log = LoggerFactory.getLogger(SomfyHome.class);
|
||||||
private Map<String, SomfyInfo> somfys;
|
private Map<String, SomfyInfo> somfys;
|
||||||
private Boolean validSomfy;
|
private Boolean validSomfy;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public SomfyHome(BridgeSettings bridgeSettings) {
|
public SomfyHome(BridgeSettings bridgeSettings) {
|
||||||
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SomfyInfo getSomfyHandler(String somfyName) {
|
public SomfyInfo getSomfyHandler(String somfyName) {
|
||||||
@@ -114,6 +117,12 @@ public class SomfyHome implements Home {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
somfys = null;
|
somfys = null;
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,13 @@ public class TCPHome implements Home {
|
|||||||
private byte[] sendData;
|
private byte[] sendData;
|
||||||
private Map<String, Socket> theSockets;
|
private Map<String, Socket> theSockets;
|
||||||
private Gson aGsonHandler;
|
private Gson aGsonHandler;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public TCPHome(BridgeSettings bridgeSettings) {
|
public TCPHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -145,6 +147,11 @@ public class TCPHome implements Home {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
log.debug("Shutting down TCP sockets.");
|
log.debug("Shutting down TCP sockets.");
|
||||||
if(theSockets != null && !theSockets.isEmpty()) {
|
if(theSockets != null && !theSockets.isEmpty()) {
|
||||||
Iterator<String> keys = theSockets.keySet().iterator();
|
Iterator<String> keys = theSockets.keySet().iterator();
|
||||||
@@ -157,6 +164,7 @@ public class TCPHome implements Home {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,14 @@ public class UDPHome implements Home {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(UDPHome.class);
|
private static final Logger log = LoggerFactory.getLogger(UDPHome.class);
|
||||||
private UDPDatagramSender theUDPDatagramSender;
|
private UDPDatagramSender theUDPDatagramSender;
|
||||||
private byte[] sendData;
|
private byte[] sendData;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public UDPHome(BridgeSettings bridgeSettings, UDPDatagramSender aUDPDatagramSender) {
|
public UDPHome(BridgeSettings bridgeSettings, UDPDatagramSender aUDPDatagramSender) {
|
||||||
super();
|
super();
|
||||||
theUDPDatagramSender = aUDPDatagramSender;
|
theUDPDatagramSender = aUDPDatagramSender;
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -104,8 +107,12 @@ public class UDPHome implements Home {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
// TODO Auto-generated method stub
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,10 +25,13 @@ public class VeraHome implements Home {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(VeraHome.class);
|
private static final Logger log = LoggerFactory.getLogger(VeraHome.class);
|
||||||
private Map<String, VeraInfo> veras;
|
private Map<String, VeraInfo> veras;
|
||||||
private Boolean validVera;
|
private Boolean validVera;
|
||||||
|
private boolean closed;
|
||||||
|
|
||||||
public VeraHome(BridgeSettings bridgeSettings) {
|
public VeraHome(BridgeSettings bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
closed = true;
|
||||||
createHome(bridgeSettings);
|
createHome(bridgeSettings);
|
||||||
|
closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Device> getDevices() {
|
public List<Device> getDevices() {
|
||||||
@@ -107,6 +110,12 @@ public class VeraHome implements Home {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void closeHome() {
|
public void closeHome() {
|
||||||
|
log.debug("Closing Home.");
|
||||||
|
if(closed) {
|
||||||
|
log.debug("Home is already closed....");
|
||||||
|
return;
|
||||||
|
}
|
||||||
veras = null;
|
veras = null;
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
<li role="presentation"><a href="#!/logs">Logs</a></li>
|
<li role="presentation"><a href="#!/logs">Logs</a></li>
|
||||||
<li role="presentation" class="active"><a href="#!/veradevices">Vera Devices</a></li>
|
<li role="presentation" class="active"><a href="#!/veradevices">Vera Devices</a></li>
|
||||||
<li role="presentation"><a href="#!/verascenes">Vera Scenes</a></li>
|
<li role="presentation"><a href="#!/verascenes">Vera Scenes</a></li>
|
||||||
<li role="presentation"><a href="#!/fibarodevices">Fibaro Devices</a></li>
|
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||||
<li role="presentation"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
<li role="presentation"><a href="#!/logs">Logs</a></li>
|
<li role="presentation"><a href="#!/logs">Logs</a></li>
|
||||||
<li role="presentation"><a href="#!/veradevices">Vera Devices</a></li>
|
<li role="presentation"><a href="#!/veradevices">Vera Devices</a></li>
|
||||||
<li role="presentation" class="active"><a href="#!/verascenes">Vera Scenes</a></li>
|
<li role="presentation" class="active"><a href="#!/verascenes">Vera Scenes</a></li>
|
||||||
<li role="presentation"><a href="#!/fibarodevices">Fibaro Devices</a></li>
|
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||||
<li role="presentation"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||||
|
|||||||
Reference in New Issue
Block a user