mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-18 16:17:30 +00:00
Finished device, scene and activity tracking, updated upnp handling, updated HUE API config handling and test on and off calls.
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>1.0.9b</version>
|
||||
<version>1.1.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
|
||||
@@ -178,6 +178,12 @@ public class DeviceRepository {
|
||||
} else if (name.equals("name")) {
|
||||
deviceEntry.setName(reader.nextString());
|
||||
log.debug("Read a Device - device json name: " + deviceEntry.getName());
|
||||
} else if (name.equals("mapType")) {
|
||||
deviceEntry.setMapType(reader.nextString());
|
||||
log.debug("Read a Device - device json name: " + deviceEntry.getMapType());
|
||||
} else if (name.equals("mapId")) {
|
||||
deviceEntry.setMapId(reader.nextString());
|
||||
log.debug("Read a Device - device json name: " + deviceEntry.getMapId());
|
||||
} else if (name.equals("deviceType")) {
|
||||
deviceEntry.setDeviceType(reader.nextString());
|
||||
log.debug("Read a Device - device json type:" + deviceEntry.getDeviceType());
|
||||
|
||||
@@ -143,8 +143,9 @@ public class DeviceResource {
|
||||
}, new JsonTransformer());
|
||||
|
||||
delete (API_CONTEXT + "/:id", "application/json", (request, response) -> {
|
||||
log.debug("Delete a device");
|
||||
DeviceDescriptor deleted = deviceRepository.findOne(request.params(":id"));
|
||||
String anId = request.params(":id");
|
||||
log.debug("Delete a device: " + anId);
|
||||
DeviceDescriptor deleted = deviceRepository.findOne(anId);
|
||||
if(deleted == null)
|
||||
response.status(HttpStatus.SC_NOT_FOUND);
|
||||
else
|
||||
|
||||
@@ -76,14 +76,7 @@ public class UpnpListener {
|
||||
byte[] buf = new byte[1024];
|
||||
DatagramPacket packet = new DatagramPacket(buf, buf.length);
|
||||
upnpMulticastSocket.receive(packet);
|
||||
String packetString = new String(packet.getData());
|
||||
if(packetString != null && packetString.contains("M-SEARCH")) {
|
||||
if(traceupnp)
|
||||
log.info("Traceupnp: SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||
else
|
||||
log.debug("Got SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||
}
|
||||
if(isSSDPDiscovery(packetString)){
|
||||
if(isSSDPDiscovery(packet)){
|
||||
sendUpnpResponse(responseSocket, packet.getAddress(), packet.getPort());
|
||||
}
|
||||
}
|
||||
@@ -97,17 +90,22 @@ public class UpnpListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* very naive ssdp discovery packet detection
|
||||
* @param body
|
||||
* @return
|
||||
* ssdp discovery packet detection
|
||||
*/
|
||||
protected boolean isSSDPDiscovery(String body){
|
||||
// log.debug("Check if this is a MAN ssdp-discover packet for a upnp basic device: " + body);
|
||||
//Only respond to discover request for upnp basic device from echo, the others are for the wemo
|
||||
if(body != null && body.contains("M-SEARCH") && body.contains("\"ssdp:discover\"")){
|
||||
if(traceupnp)
|
||||
protected boolean isSSDPDiscovery(DatagramPacket packet){
|
||||
//Only respond to discover request for strict upnp form
|
||||
String packetString = new String(packet.getData());
|
||||
if(packetString != null && packetString.startsWith("M-SEARCH * HTTP/1.1") && packetString.contains("\"ssdp:discover\"")){
|
||||
if(traceupnp) {
|
||||
log.info("Traceupnp: SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to be an M-SEARCH message.");
|
||||
if(strict && body.startsWith("M-SEARCH * HTTP/1.1") && body.contains("MAN: \"ssdp:discover\"") && (body.contains("ST: urn:schemas-upnp-org:device:basic:1") || body.contains("ST: upnp:rootdevice") || body.contains("ST: ssdp:all")))
|
||||
}
|
||||
else {
|
||||
log.debug("Got SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||
log.debug("Found message to be an M-SEARCH message.");
|
||||
}
|
||||
|
||||
if(strict && (packetString.contains("ST: urn:schemas-upnp-org:device:basic:1") || packetString.contains("ST: upnp:rootdevice") || packetString.contains("ST: ssdp:all")))
|
||||
{
|
||||
if(traceupnp)
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to be valid under strict rules - strict: " + strict);
|
||||
@@ -134,7 +132,7 @@ public class UpnpListener {
|
||||
"USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1\r\n\r\n";
|
||||
protected void sendUpnpResponse(DatagramSocket socket, InetAddress requester, int sourcePort) throws IOException {
|
||||
String discoveryResponse = null;
|
||||
discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort, getRandomUUIDString());
|
||||
discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort);
|
||||
if(traceupnp)
|
||||
log.info("Traceupnp: sendUpnpResponse: " + discoveryResponse);
|
||||
else
|
||||
@@ -142,8 +140,4 @@ public class UpnpListener {
|
||||
DatagramPacket response = new DatagramPacket(discoveryResponse.getBytes(), discoveryResponse.length(), requester, sourcePort);
|
||||
socket.send(response);
|
||||
}
|
||||
|
||||
protected String getRandomUUIDString(){
|
||||
return "88f6698f-2c83-4393-bd03-cd54a9f8595"; // https://xkcd.com/221/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public class HarmonyServer {
|
||||
log.debug("something is very wrong as dummyProvider is not null...");
|
||||
if(mySettings.isDevMode())
|
||||
modeString = " (development mode)";
|
||||
if(noopCalls)
|
||||
else if(noopCalls)
|
||||
modeString = " (no op calls to harmony)";
|
||||
log.info("setup initiated " + modeString + "....");
|
||||
if(mySettings.isDevMode())
|
||||
|
||||
@@ -191,7 +191,7 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
this.viewVeraScenes = function () {
|
||||
this.state.error = "";
|
||||
if(!this.state.showVera)
|
||||
@@ -209,7 +209,7 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
this.viewHarmonyActivities = function () {
|
||||
this.state.error = "";
|
||||
if(!this.state.showHarmony)
|
||||
@@ -246,11 +246,12 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
);
|
||||
};
|
||||
|
||||
this.findHarmonyActivityEntry = function(activityId) {
|
||||
this.findDeviceByMapId = function(id) {
|
||||
for(var i = 0; i < this.state.devices.length; i++) {
|
||||
if(this.state.devices[i].mapId == activityId)
|
||||
if(this.state.devices[i].mapId == id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.addDevice = function (device) {
|
||||
@@ -327,6 +328,13 @@ app.service('bridgeService', function ($http, $window, BridgeSettings) {
|
||||
);
|
||||
};
|
||||
|
||||
this.deleteDeviceByMapId = function (id) {
|
||||
for(var i = 0; i < this.state.devices.length; i++) {
|
||||
if(this.state.devices[i].mapId == id)
|
||||
return self.deleteDevice(this.state.devices[i].id);
|
||||
}
|
||||
};
|
||||
|
||||
this.editDevice = function (device) {
|
||||
self.state.device = device;
|
||||
};
|
||||
@@ -410,7 +418,13 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
||||
bridgeService.updateShowHarmony();
|
||||
$scope.device = bridgeService.state.device;
|
||||
$scope.activitiesVisible = false;
|
||||
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||
$scope.buttonsVisible = false;
|
||||
$scope.imgActivitiesUrl = "glyphicon glyphicon-plus";
|
||||
$scope.devicesVisible = false;
|
||||
$scope.imgDevicesUrl = "glyphicon glyphicon-plus";
|
||||
$scope.scenesVisible = false;
|
||||
$scope.imgScenesUrl = "glyphicon glyphicon-plus";
|
||||
$scope.predicate = '';
|
||||
$scope.reverse = true;
|
||||
$scope.device_dim_control = "";
|
||||
@@ -537,6 +551,7 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$scope.toggleActivities = function () {
|
||||
$scope.activitiesVisible = !$scope.activitiesVisible;
|
||||
if($scope.activitiesVisible)
|
||||
@@ -545,15 +560,43 @@ app.controller('AddingController', function ($scope, $location, $http, bridgeSer
|
||||
$scope.imgActivitiesUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
|
||||
$scope.toggleButtons = function () {
|
||||
$scope.buttonsVisible = !$scope.buttonsVisible;
|
||||
if($scope.buttonsVisible)
|
||||
$scope.imgButtonsUrl = "glyphicon glyphicon-minus";
|
||||
else
|
||||
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
|
||||
$scope.toggleDevices = function () {
|
||||
$scope.devicesVisible = !$scope.devicesVisible;
|
||||
if($scope.devicesVisible)
|
||||
$scope.imgDevicesUrl = "glyphicon glyphicon-minus";
|
||||
else
|
||||
$scope.imgDevicesUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
|
||||
$scope.toggleScenes = function () {
|
||||
$scope.scenesVisible = !$scope.scenesVisible;
|
||||
if($scope.scenesVisible)
|
||||
$scope.imgScenesUrl = "glyphicon glyphicon-minus";
|
||||
else
|
||||
$scope.imgScenesUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
|
||||
$scope.deleteDeviceByMapId = function (id) {
|
||||
bridgeService.deleteDeviceByMapId(id);
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
app.filter('availableActivity', function(bridgeService) {
|
||||
app.filter('availableId', function(bridgeService) {
|
||||
return function(input) {
|
||||
var out = [];
|
||||
if(input == null)
|
||||
return out;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if(!bridgeService.findHarmonyActivityEntry(input[i].id)){
|
||||
if(!bridgeService.findDeviceByMapId(input[i].id)){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
@@ -561,13 +604,13 @@ app.filter('availableActivity', function(bridgeService) {
|
||||
}
|
||||
});
|
||||
|
||||
app.filter('unavailableActivity', function(bridgeService) {
|
||||
app.filter('unavailableId', function(bridgeService) {
|
||||
return function(input) {
|
||||
var out = [];
|
||||
if(input == null)
|
||||
return out;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if(bridgeService.findHarmonyActivityEntry(input[i].id)){
|
||||
if(bridgeService.findDeviceByMapId(input[i].id)){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
@@ -575,6 +618,21 @@ app.filter('unavailableActivity', function(bridgeService) {
|
||||
}
|
||||
});
|
||||
|
||||
app.filter('configuredButtons', function() {
|
||||
return function(input) {
|
||||
var out = [];
|
||||
if(input == null)
|
||||
return out;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if(input[i].mapType == "harmonyButton"){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
app.controller('ErrorsController', function ($scope, bridgeService) {
|
||||
$scope.bridge = bridgeService.state;
|
||||
});
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | availableActivity | orderBy:predicate:reverse">
|
||||
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | availableId | orderBy:predicate:reverse">
|
||||
<td>{{harmonyactivity.label}}</td>
|
||||
<td>{{harmonyactivity.id}}</td>
|
||||
<td>
|
||||
@@ -58,11 +58,14 @@
|
||||
<a href="" ng-click="order('id')">Id</a>
|
||||
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | unavailableActivity | orderBy:predicate:reverse">
|
||||
<tr ng-repeat="harmonyactivity in bridge.harmonyactivities | unavailableId | orderBy:predicate:reverse">
|
||||
<td>{{harmonyactivity.label}}</td>
|
||||
<td>{{harmonyactivity.id}}</td>
|
||||
<td><button class="btn btn-danger" type="submit"
|
||||
ng-click="deleteDeviceByMapId(harmonyactivity.id)">Delete</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
|
||||
@@ -58,6 +58,41 @@
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Already Configured Harmony Buttons <a ng-click="toggleButtons()"><span class={{imgButtonsUrl}} aria-hidden="true"></span></a></h2>
|
||||
</div>
|
||||
<ul ng-if="buttonsVisible" class="list-group">
|
||||
<li class="list-group-item">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a href="" ng-click="order('name')">Name</a>
|
||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>
|
||||
<a href="" ng-click="order('id')">Device Id</a>
|
||||
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>
|
||||
<a href="" ng-click="order('mapId')">Harmony Device-Button On-Button Off</a>
|
||||
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="device in bridge.devices | configuredButtons | orderBy:predicate:reverse">
|
||||
<td>{{device.name}}</td>
|
||||
<td>{{device.id}}</td>
|
||||
<td>{{device.mapId}}</td>
|
||||
<td>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
ng-click="deleteDeviceByMapId(device.mapId)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||
<div class="panel-heading">
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation" class="active"><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 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>
|
||||
|
||||
<div ng-controller="ErrorsController">
|
||||
<div ng-if="bridge.error"
|
||||
class="alert alert-warning alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert"
|
||||
aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
|
||||
<h2 ng-show='bridge.error != ""'>ERROR</h2>
|
||||
|
||||
<div ng-show='bridge.error != ""'>{{bridge.error}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Current devices</h2>
|
||||
</div>
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a href="" ng-click="order('id')">ID</a>
|
||||
<span class="sortorder" ng-show="predicate === 'id'" ng-class="{reverse:reverse}"></span></th>
|
||||
<th>
|
||||
<a href="" ng-click="order('name')">Name</a>
|
||||
<span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span></th>
|
||||
<th>
|
||||
<a href="" ng-click="order('deviceType')">Type</a>
|
||||
<span class="sortorder" ng-show="predicate === 'deviceType'" ng-class="{reverse:reverse}"></span></th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="device in bridge.devices | orderBy:predicate:reverse">
|
||||
<td>{{device.id}}</td>
|
||||
<td>{{device.name}}</td>
|
||||
<td>{{device.deviceType}}</td>
|
||||
<td>
|
||||
<button class="btn btn-info" type="submit"
|
||||
ng-click="testUrl(device, 'on')">Test ON</button>
|
||||
<button class="btn btn-info" type="submit"
|
||||
ng-click="testUrl(device, 'off')">Test OFF</button>
|
||||
<button class="btn btn-warning" type="submit"
|
||||
ng-click="editDevice(device)">Edit</button>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
ng-click="deleteDevice(device)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="panel panel-default bridgeServer">
|
||||
<div class="panel-heading">
|
||||
<a href="#/show"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></a>
|
||||
<h1 class="panel-title">Bridge settings</h1>
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,7 +45,7 @@
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="veradevice in bridge.veradevices | orderBy:predicate:reverse">
|
||||
<tr ng-repeat="veradevice in bridge.veradevices | availableId | orderBy:predicate:reverse">
|
||||
<td>{{veradevice.name}}</td>
|
||||
<td>{{veradevice.id}}</td>
|
||||
<td>{{veradevice.category}}</td>
|
||||
@@ -59,6 +59,46 @@
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Already Configured Vera Devices <a ng-click="toggleDevices()"><span class={{imgDevicesUrl}} aria-hidden="true"></a></h2>
|
||||
</div>
|
||||
<ul ng-if="devicesVisible" class="list-group">
|
||||
<li class="list-group-item">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a href="" ng-click="order('name')">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>
|
||||
<a href="" ng-click="order('category')">Category</a>
|
||||
<span class="sortorder" ng-show="predicate === 'category'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>
|
||||
<a href="" ng-click="order('room')">Room</a>
|
||||
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="veradevice in bridge.veradevices | unavailableId | orderBy:predicate:reverse">
|
||||
<td>{{veradevice.name}}</td>
|
||||
<td>{{veradevice.id}}</td>
|
||||
<td>{{veradevice.category}}</td>
|
||||
<td>{{veradevice.room}}</td>
|
||||
<td>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
ng-click="deleteDeviceByMapId(harmonyactivity.id)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||
<div class="panel-heading">
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="verascene in bridge.verascenes | orderBy:predicate:reverse">
|
||||
<tr ng-repeat="verascene in bridge.verascenes | availableId | orderBy:predicate:reverse">
|
||||
<td>{{verascene.name}}</td>
|
||||
<td>{{verascene.id}}</td>
|
||||
<td>{{verascene.room}}</td>
|
||||
@@ -47,6 +47,41 @@
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Already Configured Vera Scenes <a ng-click="toggleScenes()"><span class={{imgScenesUrl}} aria-hidden="true"></a></h2>
|
||||
</div>
|
||||
<ul ng-if="scenesVisible" class="list-group">
|
||||
<li class="list-group-item">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a href="" ng-click="order('name')">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>
|
||||
<a href="" ng-click="order('room')">Room</a>
|
||||
<span class="sortorder" ng-show="predicate === 'room'" ng-class="{reverse:reverse}"></span>
|
||||
</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="verascene in bridge.verascenes | unavailableId | orderBy:predicate:reverse">
|
||||
<td>{{verascene.name}}</td>
|
||||
<td>{{verascene.id}}</td>
|
||||
<td>{{verascene.room}}</td>
|
||||
<td>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
ng-click="deleteDeviceByMapId(harmonyactivity.id)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel panel-default bridgeServer" ng-if="!bridge.error">
|
||||
<div class="panel-heading">
|
||||
|
||||
Reference in New Issue
Block a user