Adding button selection control for harmony. in progress....

This commit is contained in:
Admin
2015-10-30 16:30:30 -05:00
parent 59f1db285d
commit bf5ad2e23c
18 changed files with 301 additions and 106 deletions

14
pom.xml
View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId>
<version>1.0.1</version>
<version>1.0.2</version>
<packaging>jar</packaging>
<name>HA Bridge</name>
@@ -28,7 +28,7 @@
<dependency>
<groupId>com.github.bwssytems</groupId>
<artifactId>harmony-java-client</artifactId>
<version>1.0.5</version>
<version>1.0.8</version>
</dependency>
<dependency>
<groupId>com.sparkjava</groupId>
@@ -55,11 +55,6 @@
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
@@ -85,6 +80,11 @@
<artifactId>smack-core</artifactId>
<version>4.0.7</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-debug</artifactId>
<version>4.0.7</version>
</dependency>
</dependencies>
<build>

View File

@@ -42,7 +42,7 @@ public class HABridge {
String addressString;
BridgeSettings bridgeSettings;
log.info("HA Bridge (v1.0.1) starting setup....");
log.info("HA Bridge (v1.0.2) starting setup....");
//get ip address for upnp requests
try {
address = InetAddress.getLocalHost();

View File

@@ -155,10 +155,32 @@ public class DeviceResource {
get (API_CONTEXT + "/harmony/activities", "application/json", (request, response) -> {
log.debug("Get harmony activities");
if(myHarmonyHandler == null) {
response.status(HttpStatus.SC_NOT_FOUND);
return null;
}
response.status(HttpStatus.SC_OK);
if(myHarmonyHandler != null)
return myHarmonyHandler.getActivities();
return "";
return myHarmonyHandler.getActivities();
}, new JsonTransformer());
get (API_CONTEXT + "/harmony/show", "application/json", (request, response) -> {
log.debug("Get harmony current activity");
if(myHarmonyHandler == null) {
response.status(HttpStatus.SC_NOT_FOUND);
return null;
}
response.status(HttpStatus.SC_OK);
return myHarmonyHandler.getCurrentActivity();
}, new JsonTransformer());
get (API_CONTEXT + "/harmony/devices", "application/json", (request, response) -> {
log.debug("Get harmony devices");
if(myHarmonyHandler == null) {
response.status(HttpStatus.SC_NOT_FOUND);
return null;
}
response.status(HttpStatus.SC_OK);
return myHarmonyHandler.getDevices();
}, new JsonTransformer());
}

View File

@@ -6,7 +6,9 @@ import com.bwssystems.HABridge.api.hue.DeviceResponse;
import com.bwssystems.HABridge.api.hue.DeviceState;
import com.bwssystems.HABridge.api.hue.HueApiResponse;
import com.bwssystems.HABridge.dao.*;
import com.bwssystems.harmony.ButtonPress;
import com.bwssystems.harmony.HarmonyHandler;
import com.bwssystems.harmony.RunActivity;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
@@ -215,7 +217,14 @@ public class HueMulator {
if(device.getDeviceType().contains("activity"))
{
log.debug("executing activity to Harmony: " + url);
myHarmony.startActivity(url);
RunActivity anActivity = new Gson().fromJson(url, RunActivity.class);
myHarmony.startActivity(anActivity);
}
else if(device.getDeviceType().contains("button"))
{
log.debug("executing button press to Harmony: " + url);
ButtonPress aDeviceButton = new Gson().fromJson(url, ButtonPress.class);
myHarmony.pressButton(aDeviceButton);
}
else
{

View File

@@ -0,0 +1,25 @@
package com.bwssystems.harmony;
public class ButtonPress {
private String device;
private String button;
public String getDevice() {
return device;
}
public void setDevice(String device) {
this.device = device;
}
public String getButton() {
return button;
}
public void setButton(String button) {
this.button = button;
}
public Boolean isValid() {
if (device != null && !device.isEmpty()){
if (button != null && !button.isEmpty())
return true;
}
return false;
}
}

View File

@@ -41,46 +41,50 @@ public class HarmonyHandler {
return harmonyClient.getCurrentActivity();
}
public Boolean startActivity(String anActivity) {
log.debug("Harmony api start activity requested for: " + anActivity + " noop mode: " + noopCalls);
if (anActivity != null && !anActivity.isEmpty()) {
public Boolean startActivity(RunActivity anActivity) {
log.debug("Harmony api start activity requested for: " + anActivity.getName() + " noop mode: " + noopCalls);
if (anActivity.isValid()) {
try {
if (!noopCalls)
harmonyClient.startActivity(Integer.parseInt(anActivity));
harmonyClient.startActivity(Integer.parseInt(anActivity.getName()));
else
log.info("noop mode: Harmony api start activity requested for: " + anActivity.getName());
} catch (IllegalArgumentException e) {
try {
if (!noopCalls)
harmonyClient.startActivityByName(anActivity);
harmonyClient.startActivityByName(anActivity.getName());
} catch (IllegalArgumentException ei) {
log.error("Error in finding activity: " + anActivity);
log.error("Error in finding activity: " + anActivity.getName());
return false;
}
}
} else {
log.error("Error in finding activity: " + anActivity);
log.error("Error in finding activity: " + anActivity.getName());
return false;
}
return true;
}
public Boolean pressButton(String aDevice, String aDeviceButton) {
log.debug("Harmony api press a button requested for device: " + aDevice + " and a for button: " + aDeviceButton + " noop mode: " + noopCalls);
if (aDeviceButton != null && !aDeviceButton.isEmpty()) {
public Boolean pressButton(ButtonPress aDeviceButton) {
log.debug("Harmony api press a button requested for device: " + aDeviceButton.getDevice() + " and a for button: " + aDeviceButton.getButton() + " noop mode: " + noopCalls);
if (aDeviceButton.isValid()) {
try {
if (!noopCalls)
harmonyClient.pressButton(Integer.parseInt(aDevice), aDeviceButton);
harmonyClient.pressButton(Integer.parseInt(aDeviceButton.getDevice()), aDeviceButton.getButton());
else
log.info("noop mode: Harmony api press a button requested for device: " + aDeviceButton.getDevice() + " and a for button: " + aDeviceButton.getButton());
} catch (IllegalArgumentException e) {
try {
if (!noopCalls)
harmonyClient.pressButton(aDevice, aDeviceButton);
harmonyClient.pressButton(aDeviceButton.getDevice(), aDeviceButton.getButton());
} catch (IllegalArgumentException ei) {
log.error("Error in finding device: " + aDevice +" and a button: " + aDeviceButton);
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton());
return false;
}
}
} else {
log.error("Error in finding device: " + aDevice +" and a button: " + aDeviceButton);
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton());
return false;
}

View File

@@ -42,7 +42,7 @@ public class HarmonyServer {
}
private void execute(BridgeSettings mySettings) throws Exception {
log.debug("setup initiated....");
log.info("setup initiated....");
harmonyClient.addListener(new ActivityChangeListener() {
@Override
public void activityStarted(Activity activity) {

View File

@@ -0,0 +1,18 @@
package com.bwssystems.harmony;
public class RunActivity {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean isValid() {
if (name != null && !name.isEmpty())
return true;
return false;
}
}

View File

@@ -36,7 +36,7 @@
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li><a href="http://www.bwssystems.com" target="_blank">Developed by BWS Systems</a></li>
<li><a href="http://www.amazon.com/echo" target="_blank">Amazon Echo</a></li>
<li><a href="">HA Bridge Version 1.0.1</a></li>
<li><a href="">HA Bridge Version 1.0.2</a></li>
</ul>
</li>
</ul>

View File

@@ -21,6 +21,9 @@ app.config(function ($routeProvider) {
}).when('/verascenes', {
templateUrl: 'views/verascene.html',
controller: 'AddingController'
}).when('/harmonydevices', {
templateUrl: 'views/harmonydevice.html',
controller: 'AddingController'
}).when('/harmonyactivities', {
templateUrl: 'views/harmonyactivity.html',
controller: 'AddingController'
@@ -86,7 +89,7 @@ app.factory('BridgeSettings', function() {
app.service('bridgeService', function ($http, $window, BridgeSettings) {
var self = this;
self.BridgeSettings = BridgeSettings;
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", devices: [], device: [], error: "", showVera: false, showHarmony: false};
this.state = {base: window.location.origin + "/api/devices", upnpbase: window.location.origin + "/upnp/settings", huebase: window.location.origin + "/api", devices: [], device: [], error: "", showVera: false, showHarmony: false};
this.viewDevices = function () {
this.state.error = "";
@@ -210,6 +213,24 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
);
};
this.viewHarmonyDevices = function () {
this.state.error = "";
if(!this.state.showHarmony)
return;
return $http.get(this.state.base + "/harmony/devices").then(
function (response) {
self.state.harmonydevices = response.data;
},
function (error) {
if (error.data) {
$window.alert("Get Harmony Devices Error: " + error.data.message);
} else {
$window.alert("Get Harmony Devices Error: unknown");
}
}
);
};
this.addDevice = function (id, name, type, onUrl, offUrl, httpVerb, contentType, contentBody, contentBodyOff) {
this.state.error = "";
if(httpVerb != null && httpVerb != "")
@@ -302,9 +323,19 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
bridgeService.deleteDevice(device.id);
};
$scope.testUrl = function (device, type) {
if(device.deviceType == "activity")
return;
if(type == "on") {
if(device.deviceType == "activity" || device.deviceType == "button") {
$http.put($scope.bridge.huebase + "/test/lights/" + device.id + "/state", "{\"on\":true}").then(
function (response) {
$window.alert("Request Exceuted: " + response.statusText);
},
function (error) {
$window.alert("Request Error: " + error.data.message);
}
);
return;
}
if(device.httpVerb == "PUT")
$http.put(device.onUrl, device.contentBody).then(
function (response) {
@@ -327,6 +358,18 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
window.open(device.onUrl, "_blank");
}
else {
if(device.deviceType == "activity" || device.deviceType == "button") {
$http.put($scope.bridge.huebase + "/test/lights/" + device.id + "/state", "{\"on\":false}").then(
function (response) {
$window.alert("Request Exceuted: " + response.statusText);
},
function (error) {
$window.alert("Request Error: " + error.data.message);
}
);
return;
}
if(device.httpVerb == "PUT")
$http.put(device.offUrl, device.contentBodyOff).then(
function (response) {
@@ -368,6 +411,7 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
bridgeService.viewVeraDevices();
bridgeService.viewVeraScenes();
bridgeService.viewHarmonyActivities();
bridgeService.viewHarmonyDevices();
$scope.bridge = bridgeService.state;
bridgeService.updateShowVera();
bridgeService.updateShowHarmony();
@@ -450,14 +494,31 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
$scope.buildActivityUrls = function (harmonyactivity) {
$scope.device.deviceType = "activity";
$scope.device.name = harmonyactivity.label;
$scope.device.onUrl = harmonyactivity.id;
$scope.device.offUrl = "-1";
$scope.device.onUrl = "{\"name\":\"" + harmonyactivity.id + "\"}";
$scope.device.offUrl = "{\"name\":\"-1\"}";
};
$scope.buildButtonUrls = function (harmonydevice, onbutton, offbutton) {
$scope.device.deviceType = "button";
$scope.device.name = harmonydevice.label;
$scope.device.onUrl = "{\"device\":\"" + harmonydevice.id + "\",\"button\":\"" + onbutton + "\"}";
$scope.device.offUrl = "{\"device\":\"" + harmonydevice.id + "\",\"button\":\"" + offbutton + "\"}";
};
$scope.testUrl = function (device, type) {
if(device.deviceType == "activity")
return;
if(type == "on") {
if(device.deviceType == "activity" || device.deviceType == "button") {
$http.put($scope.bridge.huebase + "/test/lights/" + device.id + "/state", "{\"on\":true}").then(
function (response) {
$window.alert("Request Exceuted: " + response.statusText);
},
function (error) {
$window.alert("Request Error: " + error.data.message);
}
);
return;
}
if(device.httpVerb == "PUT")
$http.put(device.onUrl, device.contentBody).then(
function (response) {
@@ -480,6 +541,18 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
window.open(device.onUrl, "_blank");
}
else {
if(device.deviceType == "activity" || device.deviceType == "button") {
$http.put($scope.bridge.huebase + "/test/lights/" + device.id + "/state", "{\"on\":false}").then(
function (response) {
$window.alert("Request Exceuted: " + response.statusText);
},
function (error) {
$window.alert("Request Error: " + error.data.message);
}
);
return;
}
if(device.httpVerb == "PUT")
$http.put(device.offUrl, device.contentBodyOff).then(
function (response) {

View File

@@ -3,6 +3,7 @@
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
<li role="presentation"><a href="#/editor">Manual Add</a></li>
</ul>

View File

@@ -3,6 +3,7 @@
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
<li role="presentation"><a href="#/editor">Manual Add</a></li>
<li role="presentation" class="active"><a href="#/editdevice">Edit Device</a></li>
</ul>

View File

@@ -3,6 +3,7 @@
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
<li role="presentation" class="active"><a href="#/editor">Manual Add</a></li>
</ul>

View File

@@ -3,6 +3,7 @@
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li role="presentation" class="active"><a href="#/harmonyactivities">Harmony Activities</a></li>
<li role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
<li role="presentation"><a href="#/editor">Manual Add</a></li>
</ul>
@@ -19,7 +20,7 @@
<thead>
<tr>
<th>
<a href="" ng-click="order('name')">Name</a>
<a href="" ng-click="order('label')">Name</a>
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
</th>
<th>
@@ -69,9 +70,6 @@
<textarea rows="3" class="form-control" id="device-on-url"
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
</div>
<div class="clearfix visible-xs"></div>
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
ng-click="testUrl(device, 'on')">Test</button>
</div>
</div>
<div class="form-group">
@@ -83,73 +81,6 @@
<textarea rows="3" class="form-control" id="device-off-url"
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
</div>
<div class="clearfix visible-xs"></div>
<button class="col-xs-4 col-sm-2 btn btn-success" type="button"
ng-click="testUrl(device, 'off')">Test</button>
</div>
</div>
<div class="form-group">
<div class="row">
<label class="col-xs-12 col-sm-2 control-label" for="device-http-verb">Http Verb
</label>
<div class="col-xs-8 col-sm-7">
<select name="device-http-verb" id="device-http-verb" ng-model="device.httpVerb">
<option value="">---Please select---</option> <!-- not selected / blank option -->
<option value="GET">GET</option>
<option value="PUT">PUT</option>
<option value="POST">POST</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<label class="col-xs-12 col-sm-2 control-label" for="device-content-type">Content Type
</label>
<div class="col-xs-8 col-sm-7">
<select name="device-content-type" id="device-content-type" ng-model="device.contentType">
<option value="">---Please select---</option> <!-- not selected / blank option -->
<option value="application/atom+xml">application/atom+xml</option>
<option value="application/x-www-form-urlencoded">application/x-www-form-urlencoded</option>
<option value="application/json">application/json</option>
<option value="application/octet-stream">application/octet-stream</option>
<option value="application/svg+xml">application/svg+xml</option>
<option value="application/xhtml+xml">application/xhtml+xml</option>
<option value="application/xml">application/xml</option>
<option value="*">*</option>
<option value="multipart/form-data">multipart/form-data</option>
<option value="text/html">text/html</option>
<option value="text/plain">text/plain</option>
<option value="text/xml">text/xml</option>
<option value="*/*">*/*</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<label class="col-xs-12 col-sm-2 control-label"
for="device-content-body">Content Body On</label>
<div class="col-xs-8 col-sm-7">
<textarea rows="3" class="form-control" id="device-content-body"
ng-model="device.contentBody" placeholder="Content Body On for specific GET/PUT/POST type"></textarea>
</div>
<div class="clearfix visible-xs"></div>
</div>
</div>
<div class="form-group">
<div class="row">
<label class="col-xs-12 col-sm-2 control-label"
for="device-content-body-off">Content Body Off</label>
<div class="col-xs-8 col-sm-7">
<textarea rows="3" class="form-control" id="device-content-body-off"
ng-model="device.contentBodyOff" placeholder="Content Body Off for specific GET/PUT/POST type"></textarea>
</div>
<div class="clearfix visible-xs"></div>
</div>
</div>
</form>

View File

@@ -0,0 +1,107 @@
<ul class="nav nav-pills" role="tablist">
<li role="presentation"><a href="#">Configuration</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
<li role="presentation" class="active"><a href="#/harmonydevices">Harmony Devices</a></li>
<li role="presentation"><a href="#/editor">Manual Add</a></li>
</ul>
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
<div class="panel-heading">
<h2 class="panel-title">Harmony Device List</h2>
</div>
<ul class="list-group">
<li class="list-group-item">
<p class="text-muted">You can select a Harmony Device and Button and generate
the add button box selections automatically.</p>
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th>
<a href="" ng-click="order('label')">Name</a>
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
</th>
<th>
<a href="" ng-click="order('id')">Id</a>
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
</th>
<th>On Button</th>
<th>Off Button</th>
<th>Actions</th>
</tr>
</thead>
<tr ng-repeat="harmonydevice in bridge.harmonydevices | orderBy:predicate:reverse">
<td>{{harmonydevice.label}}</td>
<td>{{harmonydevice.id}}</td>
<td>
<select name="device-ctrlon" id="device-ctrlon" ng-model="devicectrlon">
<option ng-repeat="ctrlon in harmonydevice.controlGroup" value="{{ctrlon.function}}">{{ctrlon.name}}</option>
</select>
<select name="device-funcon" id="device-funcon" ng-model="devicefuncon">
<option ng-repeat="funcon in devicectrlon" value="{{funcon.name}}">{{funcon.name}}</option>
</select>
</td>
<td>
<select name="device-ctrloff" id="device-ctrloff" ng-model="devicectrloff">
<option ng-repeat="ctrloff in harmonydevice.controlGroup" value="{{ctrloff.function}}">{{ctrloff.name}}</option>
</select>
<select name="device-funcoff" id="device-funcoff" ng-model="devicefuncoff">
<option ng-repeat="funcoff in devicectrloff" value="{{funcoff.label}}">{{funcoff.label}}</option>
</select>
</td>
<td>
<button class="btn btn-success" type="submit"
ng-click="buildButtonUrls(harmonydevice, devicefuncon, devicefuncoff)">Generate
Button URLs</button>
</td>
</tr>
</table>
</li>
</ul>
</div>
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
<div class="panel-heading">
<h2 class="panel-title">Add a Harmony Button</h2>
</div>
<ul class="list-group">
<li class="list-group-item">
<form class="form-horizontal" ng-submit="addDevice()">
<div class="form-group">
<label class="col-xs-12 col-sm-2 control-label" for="device-name">Name
</label>
<div class="col-xs-8 col-sm-7">
<input type="text" class="form-control" id="device-name"
ng-model="device.name" placeholder="Device Name">
</div>
<button type="submit" class="col-xs-4 col-sm-2 btn btn-primary">
Add Button</button>
</div>
<div class="form-group">
<div class="row">
<label class="col-xs-12 col-sm-2 control-label" for="device-on-url">On
URL </label>
<div class="col-xs-8 col-sm-7">
<textarea rows="3" class="form-control" id="device-on-url"
ng-model="device.onUrl" placeholder="URL to turn device on"></textarea>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<label class="col-xs-12 col-sm-2 control-label"
for="device-off-url">Off URL </label>
<div class="col-xs-8 col-sm-7">
<textarea rows="3" class="form-control" id="device-off-url"
ng-model="device.offUrl" placeholder="URL to turn device off"></textarea>
</div>
</div>
</div>
</form>
</li>
</ul>
</div>

View File

@@ -3,6 +3,7 @@
<li ng-if="bridge.showVera" role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li ng-if="bridge.showVera" role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
<li role="presentation"><a href="#/editor">Manual Add</a></li>
</ul>

View File

@@ -3,6 +3,7 @@
<li role="presentation" class="active"><a href="#/veradevices">Vera Devices</a></li>
<li role="presentation"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
<li role="presentation"><a href="#/editor">Manual Add</a></li>
</ul>

View File

@@ -3,6 +3,7 @@
<li role="presentation"><a href="#/veradevices">Vera Devices</a></li>
<li role="presentation" class="active"><a href="#/verascenes">Vera Scenes</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonyactivities">Harmony Activities</a></li>
<li ng-if="bridge.showHarmony" role="presentation"><a href="#/harmonydevices">Harmony Devices</a></li>
<li role="presentation"><a href="#/editor">Manual Add</a></li>
</ul>