Completed HomeGenie implementation

This commit is contained in:
BWS Systems
2019-06-05 16:08:11 -05:00
parent fe0b072b4e
commit a05b933e43
37 changed files with 345 additions and 136 deletions

4
.gitignore vendored
View File

@@ -19,3 +19,7 @@ sftp-config\.json
.vscode/launch.test.json
.vscode/settings.json
.vscode/tasks.json
# dependencies
/node_modules
package-lock.json

View File

@@ -216,6 +216,7 @@ public class BridgeSettings extends BackupHandler {
theBridgeSettings.setOpenhabconfigured(theBridgeSettings.isValidOpenhab());
theBridgeSettings.setFhemconfigured(theBridgeSettings.isValidFhem());
theBridgeSettings.setMoziotconfigured(theBridgeSettings.isValidMozIot());
theBridgeSettings.setHomegenieconfigured(theBridgeSettings.isValidHomeGenie());
// Lifx is either configured or not, so it does not need an update.
if(serverPortOverride != null)
theBridgeSettings.setServerPort(serverPortOverride);

View File

@@ -2,6 +2,8 @@ package com.bwssystems.HABridge;
import com.google.gson.JsonObject;
import org.apache.commons.codec.binary.Base64;
public class NamedIP {
private String name;
private String ip;
@@ -12,6 +14,7 @@ public class NamedIP {
private JsonObject extensions;
private Boolean secure;
private String httpPreamble;
private String encodedLogin;
public String getName() {
return name;
@@ -78,14 +81,14 @@ public class NamedIP {
}
public String getHttpPreamble() {
if (httpPreamble == null || httpPreamble.length() == 0) {
if (httpPreamble == null || !httpPreamble.trim().isEmpty()) {
if (getSecure() != null && getSecure())
httpPreamble = "https://";
else
httpPreamble = "http://";
httpPreamble = httpPreamble + getIp();
if (getPort() != null && getPort().length() > 0) {
if (getPort() != null && !getPort().trim().isEmpty()) {
httpPreamble = httpPreamble + ":" + getPort();
}
}
@@ -95,4 +98,16 @@ public class NamedIP {
public void setHttpPreamble(String httpPreamble) {
this.httpPreamble = httpPreamble;
}
public String getUserPass64() {
if (encodedLogin == null || !encodedLogin.trim().isEmpty()) {
if (getUsername() != null && !getUsername().isEmpty() && getPassword() != null
&& !getPassword().isEmpty()) {
String userPass = getUsername() + ":" + getPassword();
encodedLogin = new String(Base64.encodeBase64(userPass.getBytes()));
}
}
return encodedLogin;
}
}

View File

@@ -3,12 +3,10 @@ package com.bwssystems.HABridge.plugins.domoticz;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.NamedIP;
import com.bwssystems.HABridge.api.NameValue;
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
import com.google.gson.Gson;
@@ -43,7 +41,7 @@ public class DomoticzHandler {
theUrl = buildUrl(rootRequest + type + postpend);
else
theUrl = buildUrl(rootRequest + type);
theData = httpClient.doHttpRequest(theUrl, null, null, null, buildHeaders());
theData = httpClient.doHttpRequest(theUrl, null, null, null, httpClient.addBasicAuthHeader(null, domoticzAddress));
if(theData != null) {
log.debug("GET " + type + " DomoticzApiResponse - data: " + theData);
theDomoticzApiResponse = new Gson().fromJson(theData, Devices.class);
@@ -76,15 +74,7 @@ public class DomoticzHandler {
String newUrl = null;
if(thePayload != null && !thePayload.isEmpty()) {
if(domoticzAddress.getSecure() != null && domoticzAddress.getSecure())
newUrl = "https://";
else
newUrl = "http://";
newUrl = newUrl + domoticzAddress.getIp();
if(domoticzAddress.getPort() != null && !domoticzAddress.getPort().isEmpty())
newUrl = newUrl + ":" + domoticzAddress.getPort();
newUrl = domoticzAddress.getHttpPreamble();
if(thePayload.startsWith("/"))
newUrl = newUrl + thePayload;
@@ -95,21 +85,6 @@ public class DomoticzHandler {
return newUrl;
}
public NameValue[] buildHeaders() {
NameValue[] headers = null;
if(domoticzAddress.getUsername() != null && !domoticzAddress.getUsername().isEmpty()
&& domoticzAddress.getPassword() != null && !domoticzAddress.getPassword().isEmpty()) {
NameValue theAuth = new NameValue();
theAuth.setName("Authorization");
String encoding = Base64.getEncoder().encodeToString((domoticzAddress.getUsername() + ":" + domoticzAddress.getPassword()).getBytes());
theAuth.setValue("Basic " + encoding);
headers = new NameValue[1];
headers[0] = theAuth;
}
return headers;
}
public NamedIP getDomoticzAddress() {
return domoticzAddress;
}

View File

@@ -119,7 +119,7 @@ public class DomoticzHome implements Home {
aBody = DeviceDataDecode.replaceDeviceData(aBody, device);
aBody = TimeDecode.replaceTimeValue(aBody);
}
theData = httpClient.doHttpRequest(theHandler.buildUrl(anUrl), null, null, aBody, theHandler.buildHeaders());
theData = httpClient.doHttpRequest(theHandler.buildUrl(anUrl), null, null, aBody, httpClient.addBasicAuthHeader(null, theHandler.getDomoticzAddress()));
try {
theDomoticzApiResponse = new Gson().fromJson(theData, Devices.class);
if(theDomoticzApiResponse.getStatus().equals("OK"))

View File

@@ -33,6 +33,7 @@ public class FHEMInstance {
public Boolean callCommand(String aCommand, String commandData, HTTPHandler httpClient) {
String aUrl = null;
NameValue[] headers = null;
/* Trying new code helpers
if(theFhem.getSecure() != null && theFhem.getSecure())
aUrl = "https://";
else
@@ -41,6 +42,10 @@ public class FHEMInstance {
aUrl = aUrl + theFhem.getUsername() + ":" + theFhem.getPassword() + "@";
}
aUrl = aUrl + theFhem.getIp() + ":" + theFhem.getPort() + "/" + aCommand + commandData;
*/
// New style http creation
aUrl = theFhem.getHttpPreamble() + "/" + aCommand + commandData;
headers = httpClient.addBasicAuthHeader(null, theFhem);
log.debug("calling FHEM: " + aUrl);
String theData = httpClient.doHttpRequest(aUrl, HttpPost.METHOD_NAME, "text/plain", null, headers);
if(theData != null)
@@ -54,6 +59,7 @@ public class FHEMInstance {
String theUrl = null;
String theData;
NameValue[] headers = null;
/* Trying new code helpers
if(theFhem.getSecure() != null && theFhem.getSecure())
theUrl = "https://";
else
@@ -61,7 +67,10 @@ public class FHEMInstance {
if(theFhem.getUsername() != null && !theFhem.getUsername().isEmpty() && theFhem.getPassword() != null && !theFhem.getPassword().isEmpty()) {
theUrl = theUrl + theFhem.getUsername() + ":" + theFhem.getPassword() + "@";
}
theUrl = theUrl + theFhem.getIp() + ":" + theFhem.getPort() + "/fhem?cmd=jsonlist2";
theUrl = theUrl + theFhem.getIp() + ":" + theFhem.getPort() + "/fhem?cmd=jsonlist2";
*/
theUrl = theFhem.getHttpPreamble() + "/fhem?cmd=jsonlist2";
headers = httpClient.addBasicAuthHeader(null, theFhem);
if(theFhem.getWebhook() != null && !theFhem.getWebhook().trim().isEmpty())
theUrl = theUrl + "%20room=" + theFhem.getWebhook().trim();
theData = httpClient.doHttpRequest(theUrl, HttpGet.METHOD_NAME, "application/json", null, headers);

View File

@@ -6,7 +6,6 @@ import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,7 +29,7 @@ public class FibaroInfo
{
super();
fibaroAddress = addressName;
fibaroAuth = "Basic " + new String(Base64.encodeBase64((addressName.getUsername() + ":" + addressName.getPassword()).getBytes()));
fibaroAuth = "Basic " + addressName.getUserPass64();
isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false"));
gson = new Gson();
theFilters = null;

View File

@@ -38,12 +38,8 @@ public class HomeAssistant {
log.debug("calling HomeAssistant: " + aCommand.getHassName() + " - "
+ aCommand.getEntityId() + " - " + aCommand.getState() + " - " + aCommand.getBri());
String aUrl = null;
if(hassAddress.getSecure() != null && hassAddress.getSecure())
aUrl = "https";
else
aUrl = "http";
String domain = aCommand.getEntityId().substring(0, aCommand.getEntityId().indexOf("."));
aUrl = aUrl + "://" + hassAddress.getIp() + ":" + hassAddress.getPort() + "/api/services/";
aUrl = hassAddress.getHttpPreamble() + "/api/services/";
if(domain.equals("group"))
aUrl = aUrl + "homeassistant";
else

View File

@@ -4,44 +4,40 @@ import java.util.ArrayList;
import java.util.List;
import com.bwssystems.HABridge.NamedIP;
import com.bwssystems.HABridge.api.NameValue;
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
import com.google.gson.Gson;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpPost;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HomeGenieInstance {
private static final Logger log = LoggerFactory.getLogger(HomeGenieInstance.class);
private NamedIP homegenieIP;
private NameValue[] headers;
public HomeGenieInstance(NamedIP theNamedIp, HTTPHandler httpClient) {
homegenieIP = theNamedIp;
headers = null;
// gatewayLogin(httpClient);
}
public Boolean callCommand(String deviceId, String moduleType, HomeGenieCommandDetail commandData, HTTPHandler httpClient) {
log.debug("calling HomeGenie: {}:{}{}{}", homegenieIP.getIp(), homegenieIP.getPort(), moduleType, commandData.getCommand());
public Boolean callCommand(String deviceId, String moduleType, HomeGenieCommandDetail commandData,
HTTPHandler httpClient) {
log.debug("calling HomeGenie: {}:{}{}{}", homegenieIP.getIp(), homegenieIP.getPort(), moduleType,
commandData.getCommand());
String aUrl = null;
headers = getAuthHeader();
aUrl = homegenieIP.getHttpPreamble() + "/api/" + moduleType + "/" + deviceId + "/" + commandData.getCommand();
aUrl = homegenieIP.getHttpPreamble() + "/api/" + moduleType + "/" + deviceId + "/" + commandData.getCommand();
String theLevel = commandData.getLevel();
if(commandData.getCommand().contains("Level")) {
if(theLevel != null && theLevel.length() > 0)
if (commandData.getCommand().contains("Level")) {
if (theLevel != null && theLevel.length() > 0)
aUrl = aUrl + "/" + theLevel;
else
aUrl = aUrl + "100";
}
String theData = httpClient.doHttpRequest(aUrl, HttpPut.METHOD_NAME, "application/json", null, headers);
String theData = httpClient.doHttpRequest(aUrl, HttpPut.METHOD_NAME, "application/json", null, httpClient.addBasicAuthHeader(null, homegenieIP));
log.debug("call Command return is: <<<{}>>>", theData);
if (!theData.contains("OK"))
return false;
@@ -55,11 +51,9 @@ public class HomeGenieInstance {
String theUrl = null;
String theData;
headers = getAuthHeader();
theUrl = homegenieIP.getHttpPreamble() + "/api/HomeAutomation.HomeGenie/Config/Modules.List";
theUrl = theUrl + homegenieIP.getHttpPreamble() + "/api/HomeAutomation.HomeGenie/Config/Modules.List";
theData = httpClient.doHttpRequest(theUrl, HttpGet.METHOD_NAME, "application/json", null, headers);
theData = httpClient.doHttpRequest(theUrl, HttpGet.METHOD_NAME, "application/json", null, httpClient.addBasicAuthHeader(null, homegenieIP));
if (theData != null) {
log.debug("GET HomeGenie Devices - data: " + theData);
try {
@@ -67,7 +61,7 @@ public class HomeGenieInstance {
if (hgModules != null && hgModules.length > 0) {
deviceList = new ArrayList<Module>();
for (int i = 0; i < hgModules.length; i++) {
if(hgModules[i].isSwitch() || hgModules[i].isDimmer())
if (hgModules[i].isSwitch() || hgModules[i].isDimmer())
deviceList.add(hgModules[i]);
}
}
@@ -78,59 +72,6 @@ public class HomeGenieInstance {
return deviceList;
}
private NameValue[] getAuthHeader() {
/* if (headers == null) {
headers = new NameValue[3];
headers[0] = new NameValue();
headers[0].setName("Authorization");
headers[0].setValue("Bearer " + moziotToken.getJwt());
headers[1] = new NameValue();
headers[1].setName("Content-Type");
headers[1].setValue("application/json");
headers[2] = new NameValue();
headers[2].setName("Accept");
headers[2].setValue("application/json");
}
*/
return headers;
}
private void gatewayLogin(HTTPHandler httpClient) {
/* String aUrl = null;
if (homegenieIP.getSecure() != null && homegenieIP.getSecure())
aUrl = "https://";
else
aUrl = "http://";
headers = new NameValue[2];
headers[0] = new NameValue();
headers[0].setName("Content-Type");
headers[0].setValue("application/json");
headers[1] = new NameValue();
headers[1].setName("Accept");
headers[1].setValue("application/json");
aUrl = aUrl + homegenieIP.getIp() + ":" + homegenieIP.getPort() + "/login";
log.debug("gateway login URL: {}", aUrl);
String commandData = "{\"email\": \"" + homegenieIP.getUsername() + "\", \"password\":\"" + homegenieIP.getPassword()
+ "\"}";
log.debug("The login body: {}", commandData);
String theData = httpClient.doHttpRequest(aUrl, HttpPost.METHOD_NAME, "application/json", commandData, headers);
if (theData != null) {
log.debug("GET Mozilla login - data: {}", theData);
try {
moziotToken = new Gson().fromJson(theData, JWT.class);
} catch (Exception e) {
log.warn("Cannot get login for HomeGenie {} Gson Parse Error.", homegenieIP.getName());
}
} else {
log.warn("Could not login {} error: <<<{}>>>", homegenieIP.getName(), theData);
}
headers = null;
*/
}
public NamedIP getHomegenieIP() {
return homegenieIP;
}

View File

@@ -1,7 +1,7 @@
package com.bwssystems.HABridge.plugins.homegenie;
import java.util.List;
// import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
@@ -22,9 +22,11 @@ public class Module {
@SerializedName("Address")
@Expose
private String address;
/*
@SerializedName("Properties")
@Expose
private List<Property> properties = null;
*/
@SerializedName("RoutingNode")
@Expose
private String routingNode;
@@ -68,7 +70,7 @@ public class Module {
public void setAddress(String address) {
this.address = address;
}
/*
public List<Property> getProperties() {
return properties;
}
@@ -76,7 +78,7 @@ public class Module {
public void setProperties(List<Property> properties) {
this.properties = properties;
}
*/
public String getRoutingNode() {
return routingNode;
}
@@ -86,14 +88,17 @@ public class Module {
}
public boolean isSwitch() {
return isPropertyType("Switch");
return isDeviceType("Switch");
}
public boolean isDimmer() {
return isPropertyType("Dimmer");
return isDeviceType("Dimmer");
}
private boolean isPropertyType(String theType) {
private boolean isDeviceType(String theType) {
if(deviceType.equals(theType)) {
return true;
}
return false;
}
}

View File

@@ -9,8 +9,6 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,7 +44,7 @@ public class HomeWizzardSmartPlugInfo {
super();
cloudAuth = "Basic " + new String(Base64.encodeBase64((gateway.getUsername() + ":" + DigestUtils.sha1Hex(gateway.getPassword())).getBytes()));
cloudAuth = "Basic " + gateway.getUserPass64();
cloudPlugName = name;
gson = new Gson();
}

View File

@@ -18,6 +18,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.DeviceMapTypes;
import com.bwssystems.HABridge.NamedIP;
import com.bwssystems.HABridge.api.NameValue;
public class HTTPHandler {
@@ -168,6 +169,35 @@ public class HTTPHandler {
return theContent;
}
public NameValue[] addBasicAuthHeader(NameValue[] theHeaders, NamedIP theTarget) {
NameValue[] headers = null;
int index = 0;
String encodedLogin = theTarget.getUserPass64();
if (encodedLogin != null && !encodedLogin.trim().isEmpty()) {
if (theHeaders != null && theHeaders.length > 0) {
headers = new NameValue[theHeaders.length + 1];
for(int i = 0; i < theHeaders.length; i++) {
headers[i] = theHeaders[i];
}
index = theHeaders.length;
} else {
headers = new NameValue[1];
}
log.debug("creating login for {} with username {} password len {}", theTarget.getName(),
theTarget.getUsername(), theTarget.getPassword().length());
headers[index] = new NameValue();
headers[index].setName("Authorization");
// log.debug("Encoded login info {}", encodedLogin);
headers[index].setValue("Basic " + encodedLogin);
} else {
headers = theHeaders;
}
return headers;
}
public void setCallType(String callType) {
this.callType = callType;
}

View File

@@ -33,16 +33,13 @@ public class OpenHABInstance {
public Boolean callCommand(String aCommand, String commandData, HTTPHandler httpClient) {
log.debug("calling OpenHAB: " + theOpenHAB.getIp() + ":" + theOpenHAB.getPort() + aCommand);
String aUrl = null;
NameValue[] headers = null;
if(theOpenHAB.getSecure() != null && theOpenHAB.getSecure())
aUrl = "https://";
else
aUrl = "http://";
if(theOpenHAB.getUsername() != null && !theOpenHAB.getUsername().isEmpty() && theOpenHAB.getPassword() != null && !theOpenHAB.getPassword().isEmpty()) {
aUrl = aUrl + theOpenHAB.getUsername() + ":" + theOpenHAB.getPassword() + "@";
}
aUrl = aUrl + theOpenHAB.getIp() + ":" + theOpenHAB.getPort() + "/" + aCommand;
String theData = httpClient.doHttpRequest(aUrl, HttpPost.METHOD_NAME, "text/plain", commandData, headers);
String theData = httpClient.doHttpRequest(aUrl, HttpPost.METHOD_NAME, "text/plain", commandData, httpClient.addBasicAuthHeader(null, theOpenHAB));
log.debug("call Command return is: <" + theData + ">");
if(theData.contains("error") || theData.contains("ERROR") || theData.contains("Error"))
return false;

View File

@@ -95,6 +95,10 @@ app.config(function ($locationProvider, $routeProvider) {
templateUrl: 'views/broadlinkdevice.html',
controller: 'BroadlinkController',
requiresAuthentication: true
}).when('/homegeniedevices', {
templateUrl: 'views/homegeniedevice.html',
controller: 'HomeGenieController',
requiresAuthentication: true
}).when('/login', {
templateUrl: 'views/login.html',
controller: 'LoginController'
@@ -194,6 +198,7 @@ app.service('bridgeService', function ($rootScope, $http, $base64, $location, ng
showMozIot: false,
showFHEM: false,
showBroadlink: false,
showHomeGenie: false,
habridgeversion: {},
viewDevId: "",
queueDevId: "",
@@ -636,6 +641,11 @@ app.service('bridgeService', function ($rootScope, $http, $base64, $location, ng
return;
};
this.updateShowHomeGenie = function () {
this.state.showHomeGenie = self.state.settings.homegenieconfigured;
return;
};
this.loadBridgeSettings = function () {
return $http.get(this.state.systemsbase + "/settings").then(
function (response) {
@@ -656,6 +666,7 @@ app.service('bridgeService', function ($rootScope, $http, $base64, $location, ng
self.updateShowMozIot();
self.updateShowFhem();
self.updateShowBroadlink();
self.updateShowHomeGenie();
},
function (error) {
if (error.status === 401)
@@ -1022,7 +1033,23 @@ app.service('bridgeService', function ($rootScope, $http, $base64, $location, ng
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get broadlink Devices Error: ", error);
self.displayWarn("Get Broadlink Devices Error: ", error);
}
);
};
this.viewHomeGenieDevices = function () {
if (!this.state.showHomeGenie)
return;
return $http.get(this.state.base + "/homegenie/devices").then(
function (response) {
self.state.homegeniedevices = response.data;
},
function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get HomeGenie Devices Error: ", error);
}
);
};
@@ -1885,7 +1912,7 @@ app.controller('SystemController', function ($scope, $location, bridgeService, n
}
};
$scope.addMozIottoSettings = function (newmoziotname, newmoziotip, newmoziotport, newmoziotusername, newmoziotpassword, newmoziotsecure) {
$scope.addMozIottoSettings = function (newmoziotname, newmoziotip, newmoziotport, newmoziotusername, newmoziotpassword, newmoziotwebhook, newmoziotsecure) {
if ($scope.bridge.settings.moziotaddress === undefined || $scope.bridge.settings.moziotaddress === null) {
$scope.bridge.settings.moziotaddress = {
devices: []
@@ -1897,6 +1924,7 @@ app.controller('SystemController', function ($scope, $location, bridgeService, n
port: newmoziotport,
username: newmoziotusername,
password: newmoziotpassword,
webhook: newmoziotwebhook,
secure: newmoziotsecure
};
$scope.bridge.settings.moziotaddress.devices.push(newmoziot);
@@ -1905,6 +1933,7 @@ app.controller('SystemController', function ($scope, $location, bridgeService, n
$scope.newmoziotport = "4443";
$scope.newmoziotusername = null;
$scope.newmoziotpassword = null;
$scope.newmoziotwebhook = null;
};
$scope.removeMozIottoSettings = function (moziotname, moziotip) {
for (var i = $scope.bridge.settings.moziotaddress.devices.length - 1; i >= 0; i--) {
@@ -1945,6 +1974,37 @@ app.controller('SystemController', function ($scope, $location, bridgeService, n
}
};
$scope.addHomeGenietoSettings = function (newhomegeniename, newhomegenieip, newhomegenieport, newhomegenieusername, newhomegeniepassword, newhomegeniewebhook, newhomegeniesecure) {
if ($scope.bridge.settings.homegenieaddress === undefined || $scope.bridge.settings.homegenieaddress === null) {
$scope.bridge.settings.homegenieaddress = {
devices: []
};
}
var newhomegenie = {
name: newhomegeniename,
ip: newhomegenieip,
port: newhomegenieport,
username: newhomegenieusername,
password: newhomegeniepassword,
secure: newhomegeniesecure,
webhook: newhomegeniewebhook
};
$scope.bridge.settings.homegenieaddress.devices.push(newhomegenie);
$scope.newhomegeniename = null;
$scope.newhomegenieip = null;
$scope.newhomegenieport = "8080";
$scope.newhomegenieusername = null;
$scope.newhomegeniepassword = null;
$scope.newhomegeniewebhook = null;
};
$scope.removeHomeGenietoSettings = function (homegeniename, homegenieip) {
for (var i = $scope.bridge.settings.homegenieaddress.devices.length - 1; i >= 0; i--) {
if ($scope.bridge.settings.homegenieaddress.devices[i].name === homegeniename && $scope.bridge.settings.homegenieaddress.devices[i].ip === homegenieip) {
$scope.bridge.settings.homegenieaddress.devices.splice(i, 1);
}
}
};
$scope.bridgeReinit = function () {
bridgeService.reinit();
};
@@ -3504,7 +3564,7 @@ app.controller('HomeWizardController', function ($scope, $location, bridgeServic
function () {
$scope.clearDevice();
bridgeService.viewDevices();
bridgeService.viewHalDevices();
bridgeService.viewHomeWizardDevices();
},
function (error) {
bridgeService.displayWarn("Error adding HomeWizard devices in bulk.", error);
@@ -3664,7 +3724,7 @@ app.controller('DomoticzController', function ($scope, $location, bridgeService,
function () {
$scope.clearDevice();
bridgeService.viewDevices();
bridgeService.viewHalDevices();
bridgeService.viewDomoticzDevices();
},
function (error) {
bridgeService.displayWarn("Error adding Domoticz devices in bulk.", error);
@@ -3797,7 +3857,7 @@ app.controller('LifxController', function ($scope, $location, bridgeService, ngD
function () {
$scope.clearDevice();
bridgeService.viewDevices();
bridgeService.viewHalDevices();
bridgeService.viewLifxDevices();
},
function (error) {
bridgeService.displayWarn("Error adding LIFX devices in bulk.", error);
@@ -4098,7 +4158,7 @@ app.controller('OpenHABController', function ($scope, $location, bridgeService,
function () {
$scope.clearDevice();
bridgeService.viewDevices();
bridgeService.viewHalDevices();
bridgeService.viewOpenHABDevices();
},
function (error) {
bridgeService.displayWarn("Error adding openhab devices in bulk.", error);
@@ -4240,7 +4300,7 @@ app.controller('MozIotController', function ($scope, $location, bridgeService, n
function () {
$scope.clearDevice();
bridgeService.viewDevices();
bridgeService.viewHalDevices();
bridgeService.viewMozIotDevices();
},
function (error) {
bridgeService.displayWarn("Error adding Mozilla IOT devices in bulk.", error);
@@ -4384,7 +4444,7 @@ app.controller('FhemController', function ($scope, $location, bridgeService, ngD
function () {
$scope.clearDevice();
bridgeService.viewDevices();
bridgeService.viewHalDevices();
bridgeService.viewFhemDevices();
},
function (error) {
bridgeService.displayWarn("Error adding fhem devices in bulk.", error);
@@ -4543,7 +4603,7 @@ app.controller('BroadlinkController', function ($scope, $location, bridgeService
function () {
$scope.clearDevice();
bridgeService.viewDevices();
bridgeService.viewHalDevices();
bridgeService.viewBroadlinkDevices();
},
function (error) {
bridgeService.displayWarn("Error adding openhab devices in bulk.", error);
@@ -4610,6 +4670,146 @@ app.controller('BroadlinkController', function ($scope, $location, bridgeService
};
});
app.controller('HomeGenieController', function ($scope, $location, bridgeService, ngDialog) {
$scope.bridge = bridgeService.state;
$scope.device = bridgeService.state.device;
$scope.device_dim_control = "";
$scope.bulk = {
devices: []
};
$scope.selectAll = false;
bridgeService.viewHomeGenieDevices();
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
$scope.buttonsVisible = false;
$scope.clearDevice = function () {
bridgeService.clearDevice();
$scope.device = bridgeService.state.device;
};
$scope.buildDeviceUrls = function (homegeniedevice, dim_control, coloraction, colordata, buildonly) {
var preCmd = "{\"moduleType\":\"" + homegeniedevice.deviceDetail.Domain + "\",\"deviceId\":\"" + homegeniedevice.deviceDetail.Address + "\",\"command\":";
onpayload = null;
offpayload = null;
dimpayload = null;
colorpayload = null;
onpayload = preCmd + "{\"command\":\"Control.On\"}}";
offpayload = preCmd + "{\"command\":\"Control.Off\"}}";
if (dim_control !== undefined && dim_control !== "") {
dimpayload = preCmd + "{\"command\":\"Control.Level\",\"level\":\"" + dim_control + "\"}}";
}
// if (coloraction === 'other')
// colorpayload = "{\"url\":\"" + preCmd + "color\",\"command\":{\"color\":\"" + colordata + "\"}}";
// else if (coloraction !== undefined && coloraction !== null && coloraction !== '')
// colorpayload = "{\"url\":\"" + preCmd + "color\",\"command\":{\"color\":\"" + coloraction + "\"}}";
bridgeService.buildUrls(onpayload, dimpayload, offpayload, colorpayload, true, homegeniedevice.deviceDetail.Name + "-" + homegeniedevice.deviceDetail.DeviceType, homegeniedevice.deviceDetail.Name, homegeniedevice.gatewayName, homegeniedevice.deviceDetail.DeviceType, "homegenieDevice", null, null);
$scope.device = bridgeService.state.device;
if (!buildonly) {
bridgeService.editNewDevice($scope.device);
$location.path('/editdevice');
}
};
$scope.bulkAddDevices = function (dim_control) {
var devicesList = [];
$scope.clearDevice();
for (var i = 0; i < $scope.bulk.devices.length; i++) {
for (var x = 0; x < bridgeService.state.homegeniedevices.length; x++) {
if (bridgeService.state.homegeniedevices[x].devicename === $scope.bulk.devices[i]) {
$scope.buildDeviceUrls(bridgeService.state.homegeniedevices[x], dim_control, null, null, true);
devicesList[i] = {
name: $scope.device.name,
mapId: $scope.device.mapId,
mapType: $scope.device.mapType,
deviceType: $scope.device.deviceType,
targetDevice: $scope.device.targetDevice,
onUrl: $scope.device.onUrl,
dimUrl: $scope.device.dimUrl,
offUrl: $scope.device.offUrl,
colorUrl: $scope.device.colorUrl,
headers: $scope.device.headers,
httpVerb: $scope.device.httpVerb,
contentType: $scope.device.contentType,
contentBody: $scope.device.contentBody,
contentBodyDim: $scope.device.contentBodyDim,
contentBodyOff: $scope.device.contentBodyOff
};
$scope.clearDevice();
}
}
}
bridgeService.bulkAddDevice(devicesList).then(
function () {
$scope.clearDevice();
bridgeService.viewDevices();
bridgeService.viewHomeGenieDevices();
},
function (error) {
bridgeService.displayWarn("Error adding HomeGenie devices in bulk.", error);
}
);
$scope.bulk = {
devices: []
};
$scope.selectAll = false;
};
$scope.toggleSelection = function toggleSelection(deviceId) {
var idx = $scope.bulk.devices.indexOf(deviceId);
// is currently selected
if (idx > -1) {
$scope.bulk.devices.splice(idx, 1);
if ($scope.bulk.devices.length === 0 && $scope.selectAll)
$scope.selectAll = false;
}
// is newly selected
else {
$scope.bulk.devices.push(deviceId);
$scope.selectAll = true;
}
};
$scope.toggleSelectAll = function toggleSelectAll() {
if ($scope.selectAll) {
$scope.selectAll = false;
$scope.bulk = {
devices: []
};
} else {
$scope.selectAll = true;
for (var x = 0; x < bridgeService.state.homegeniedevices.length; x++) {
if ($scope.bulk.devices.indexOf(bridgeService.state.homegeniedevices[x]) < 0)
$scope.bulk.devices.push(bridgeService.state.homegeniedevices[x].devicename);
}
}
};
$scope.toggleButtons = function () {
$scope.buttonsVisible = !$scope.buttonsVisible;
if ($scope.buttonsVisible)
$scope.imgButtonsUrl = "glyphicon glyphicon-minus";
else
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
};
$scope.deleteDevice = function (device) {
$scope.bridge.device = device;
ngDialog.open({
template: 'deleteDialog',
controller: 'DeleteDialogCtrl',
className: 'ngdialog-theme-default'
});
};
$scope.editDevice = function (device) {
bridgeService.editDevice(device);
$location.path('/editdevice');
};
});
app.controller('EditController', function ($scope, $location, bridgeService) {
$scope.bridge = bridgeService.state;
$scope.device = bridgeService.state.device;
@@ -5127,6 +5327,20 @@ app.filter('configuredMozIotItems', function (bridgeService) {
};
});
app.filter('configuredHomeGenieItems', function (bridgeService) {
return function (input) {
var out = [];
if (input === undefined || input === null || input.length === undefined)
return out;
for (var i = 0; i < input.length; i++) {
if (bridgeService.deviceContainsType(input[i], "homegenie")) {
out.push(input[i]);
}
}
return out;
};
});
app.filter('filterDevicesByRequester', function () {
return function (input, search, mustContain, deviceType) {
var out = [];

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation" class="active"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -22,6 +22,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>
<div postrender-action="goToRow()">

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -22,6 +22,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation" class="active"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation" class="active"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,7 +21,8 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation" class="active"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation" class="active"><a href="#!/homegeniedevices">HomeGenie
Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>
@@ -63,6 +64,7 @@
<th sortable-header col="name">
<span><input type="checkbox" name="selectAll" value="{{selectAll}}" ng-checked="selectAll"
ng-click="toggleSelectAll()"> Name</span></th>
<th sortable-header col="domain">Domain</th>
<th sortable-header col="type">Type</th>
<th sortable-header col="homegeniename">HomeGenie</th>
<th>Build Actions</th>
@@ -74,11 +76,12 @@
ng-checked="bulk.devices.indexOf(homegeniedevice.deviceDetail.Name) > -1"
ng-click="toggleSelection(homegeniedevice.deviceDetail.Name)">
{{homegeniedevice.deviceDetail.Name}}</td>
<td>{{homegeniedevice.deviceDetail.DeviceType}}</td>
<td>{{homegeniedevice.deviceDetail.Domain}}</td>
<td>{{homegeniedevice.deviceDetail.DeviceType}}</td>
<td>{{homegeniedevice.gatewayName}}</td>
<td>
<button class="btn btn-success" type="submit"
ng-click="buildDeviceUrls(homegeniedevice, device_dim_control, false)">Build
ng-click="buildDeviceUrls(homegeniedevice, device_dim_control, null, null, false)">Build
Item</button>
</td>
</tr>
@@ -111,7 +114,7 @@
<th>Actions</th>
</tr>
</thead>
<tr ng-repeat="device in bridge.devices | configuredMozIotItems">
<tr ng-repeat="device in bridge.devices | configuredHomeGenieItems">
<td>{{$index+1}}</td>
<td>{{device.name}}</td>
<td>{{device.deviceType}}</td>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -19,6 +19,7 @@
<li ng-if="bridge.showHomeWizard" role="presentation"><a href="#!/homewizarddevices">HomeWizard Devices</a></li>
<li ng-if="bridge.showOpenHAB" role="presentation"><a href="#!/openhabdevices">OpenHAB Devices</a></li>
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation" class="active"><a href="#!/moziotdevices">Mozilla IOT Devices</a>
</li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>

View File

@@ -21,6 +21,7 @@
<li ng-if="bridge.showFHEM" role="presentation"><a href="#!/fhemdevices">FHEM Devices</a></li>
<li ng-if="bridge.showMozIot" role="presentation"><a href="#!/moziotdevices">Mozilla IOT Devices</a></li>
<li ng-if="bridge.showBroadlink" role="presentation"><a href="#!/broadlinkdevices">Broadlink Devices</a></li>
<li ng-if="bridge.showHomeGenie" role="presentation"><a href="#!/homegeniedevices">HomeGenie Devices</a></li>
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
</ul>