mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-16 18:24:36 +00:00
Updated scrollable table header sorts for config, vera and harmony
Added upnp notification logic
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>4beta3</version>
|
||||
<version>4beta3.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
|
||||
@@ -12,4 +12,5 @@ public class Configuration {
|
||||
public static final String UPNP_MULTICAST_ADDRESS = "239.255.255.250";
|
||||
public static final String CONFIG_FILE = "data/habridge.config";
|
||||
public static final int NUMBER_OF_LOG_MESSAGES = 512;
|
||||
public static final long UPNP_NOTIFY_TIMEOUT = 20000;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ import com.bwssystems.HABridge.util.UDPDatagramSender;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Enumeration;
|
||||
import org.apache.http.conn.util.*;
|
||||
|
||||
@@ -25,6 +26,9 @@ public class UpnpListener {
|
||||
private boolean strict;
|
||||
private boolean traceupnp;
|
||||
private BridgeControlDescriptor bridgeControl;
|
||||
private String bridgeId;
|
||||
private String bridgeSNUUID;
|
||||
private HuePublicConfig aHueConfig;
|
||||
private String responseTemplate1 = "HTTP/1.1 200 OK\r\n" +
|
||||
"HOST: %s:%s\r\n" +
|
||||
"CACHE-CONTROL: max-age=100\r\n" +
|
||||
@@ -53,6 +57,16 @@ public class UpnpListener {
|
||||
"ST: urn:schemas-upnp-org:device:basic:1\r\n" +
|
||||
"USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n";
|
||||
|
||||
private String notifyTemplate = "NOTIFY * HTTP/1.1\r\n" +
|
||||
"HOST: %s:%s\r\n" +
|
||||
"CACHE-CONTROL: max-age=100\r\n" +
|
||||
"LOCATION: http://%s:%s/description.xml\r\n" +
|
||||
"SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/" + HueConstants.API_VERSION + "\r\n" +
|
||||
"NTS: ssdp:alive\r\n" +
|
||||
"hue-bridgeid: %s\r\n" +
|
||||
"NT: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n" +
|
||||
"USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n";
|
||||
|
||||
public UpnpListener(BridgeSettingsDescriptor theSettings, BridgeControlDescriptor theControl, UDPDatagramSender aUdpDatagramSender) {
|
||||
super();
|
||||
theUDPDatagramSender = aUdpDatagramSender;
|
||||
@@ -61,6 +75,9 @@ public class UpnpListener {
|
||||
strict = theSettings.isUpnpStrict();
|
||||
traceupnp = theSettings.isTraceupnp();
|
||||
bridgeControl = theControl;
|
||||
aHueConfig = HuePublicConfig.createConfig("temp", responseAddress, HueConstants.HUB_VERSION);
|
||||
bridgeId = aHueConfig.getBridgeid();
|
||||
bridgeSNUUID = aHueConfig.getSNUUIDFromMac();
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
@@ -118,6 +135,13 @@ public class UpnpListener {
|
||||
log.info("UPNP Discovery Listener running and ready....");
|
||||
boolean loopControl = true;
|
||||
boolean error = false;
|
||||
try {
|
||||
upnpMulticastSocket.setSoTimeout((int) Configuration.UPNP_NOTIFY_TIMEOUT);
|
||||
} catch (SocketException e1) {
|
||||
log.warn("Could not sent soTimeout on multi-cast socket");
|
||||
}
|
||||
Instant current, previous;
|
||||
previous = Instant.now();
|
||||
while (loopControl) { // trigger shutdown here
|
||||
byte[] buf = new byte[1024];
|
||||
DatagramPacket packet = new DatagramPacket(buf, buf.length);
|
||||
@@ -131,6 +155,15 @@ public class UpnpListener {
|
||||
log.debug("UpnpListener send upnp exception: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
current = Instant.now();
|
||||
if(ChronoUnit.MILLIS.between(previous, current) > Configuration.UPNP_NOTIFY_TIMEOUT) {
|
||||
sendUpnpNotify(socketAddress.getAddress(), upnpMulticastSocket);
|
||||
previous = Instant.now();
|
||||
}
|
||||
|
||||
} catch (SocketTimeoutException e) {
|
||||
sendUpnpNotify(socketAddress.getAddress(), upnpMulticastSocket);
|
||||
} catch (IOException e) {
|
||||
log.error("UpnpListener encountered an error reading socket. Shutting down", e);
|
||||
error = true;
|
||||
@@ -198,11 +231,6 @@ public class UpnpListener {
|
||||
|
||||
protected void sendUpnpResponse(InetAddress requester, int sourcePort) throws IOException {
|
||||
String discoveryResponse = null;
|
||||
String bridgeId = null;
|
||||
String bridgeSNUUID = null;
|
||||
HuePublicConfig aHueConfig = HuePublicConfig.createConfig("temp", responseAddress, HueConstants.HUB_VERSION);
|
||||
bridgeId = aHueConfig.getBridgeid();
|
||||
bridgeSNUUID = aHueConfig.getSNUUIDFromMac();
|
||||
discoveryResponse = String.format(responseTemplate1, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID);
|
||||
if(traceupnp) {
|
||||
log.info("Traceupnp: sendUpnpResponse discovery responseTemplate1 is <<<" + discoveryResponse + ">>>");
|
||||
@@ -227,4 +255,21 @@ public class UpnpListener {
|
||||
log.debug("sendUpnpResponse discovery responseTemplate3 is <<<" + discoveryResponse + ">>>");
|
||||
theUDPDatagramSender.sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
||||
}
|
||||
|
||||
protected void sendUpnpNotify(InetAddress aSocketAddress, MulticastSocket theUpnpMulticastSocket) {
|
||||
String notifyData = null;
|
||||
log.debug("Sending notify packet for upnp.");
|
||||
notifyData = String.format(notifyTemplate, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
|
||||
if(traceupnp) {
|
||||
log.info("Traceupnp: sendUpnpNotify notifyTemplate is <<<" + notifyData + ">>>");
|
||||
}
|
||||
DatagramPacket notifyPacket = new DatagramPacket(notifyData.getBytes(), notifyData.length(), aSocketAddress, Configuration.UPNP_DISCOVERY_PORT);
|
||||
try {
|
||||
theUpnpMulticastSocket.send(notifyPacket);
|
||||
} catch (IOException e1) {
|
||||
log.warn("UpnpListener encountered an error sending upnp notify packet. IP: " + notifyPacket.getAddress().getHostAddress() + " with message: " + e1.getMessage());
|
||||
log.debug("UpnpListener send upnp notify exception: ", e1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +132,12 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
|
||||
);
|
||||
};
|
||||
|
||||
this.compareUniqueId = function(r1, r2) {
|
||||
if (r1.id === r2.id)
|
||||
return 0;
|
||||
return parseInt(r1.id) > parseInt(r2.id) ? 1 : -1;
|
||||
};
|
||||
|
||||
this.clearDevice = function () {
|
||||
self.state.device = {};
|
||||
self.state.olddevicename = "";
|
||||
@@ -152,6 +158,43 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
|
||||
return a.indexOf(b) >= 0;
|
||||
}
|
||||
|
||||
this.compareHarmonyNumber = function(r1, r2) {
|
||||
if (r1.device !== undefined) {
|
||||
if (r1.device.id === r2.device.id)
|
||||
return 0;
|
||||
return r1.device.id > r2.device.id ? 1 : -1;
|
||||
}
|
||||
if (r1.activity !== undefined) {
|
||||
if (r1.activity.id === r2.activity.id)
|
||||
return 0;
|
||||
return r1.activity.id > r2.activity.id ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.compareHarmonyLabel = function(r1, r2) {
|
||||
if (r1.device !== undefined) {
|
||||
if (r1.device.label === r2.device.label)
|
||||
return 0;
|
||||
return r1.device.label > r2.device.label ? 1 : -1;
|
||||
}
|
||||
if (r1.activity !== undefined) {
|
||||
if (r1.activity.label === r2.activity.label)
|
||||
return 0;
|
||||
return r1.activity.label > r2.activity.label ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.compareHarmonyHub = function(r1, r2) {
|
||||
if (r1.hub !== undefined) {
|
||||
if (r1.hub === r2.hub)
|
||||
return 0;
|
||||
return r1.hub > r2.hub ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
this.updateShowVera = function () {
|
||||
this.state.showVera = self.state.settings.veraconfigured;
|
||||
return;
|
||||
@@ -961,6 +1004,7 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
||||
$scope.imgUrl = "glyphicon glyphicon-plus";
|
||||
$scope.visibleBk = false;
|
||||
$scope.imgBkUrl = "glyphicon glyphicon-plus";
|
||||
$scope.comparatorUniqueId = bridgeService.compareUniqueId;
|
||||
$scope.testUrl = function (device, type) {
|
||||
var dialogNeeded = false;
|
||||
if((type === "on" && (bridgeService.aContainsB(device.onUrl, "${intensity.byte}") ||
|
||||
@@ -1107,6 +1151,7 @@ app.controller('VeraController', function ($scope, $location, $http, bridgeServi
|
||||
bridgeService.viewVeraScenes();
|
||||
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||
$scope.buttonsVisible = false;
|
||||
$scope.comparatorUniqueId = bridgeService.compareUniqueId;
|
||||
|
||||
$scope.clearDevice = function () {
|
||||
bridgeService.clearDevice();
|
||||
@@ -1261,6 +1306,9 @@ app.controller('HarmonyController', function ($scope, $location, $http, bridgeSe
|
||||
bridgeService.viewHarmonyDevices();
|
||||
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||
$scope.buttonsVisible = false;
|
||||
$scope.comparatorNumber = bridgeService.compareHarmonyNumber;
|
||||
$scope.comparatorLabel = bridgeService.compareHarmonyLabel;
|
||||
$scope.comparatorHub = bridgeService.compareHarmonyHub;
|
||||
|
||||
$scope.clearDevice = function () {
|
||||
bridgeService.clearDevice();
|
||||
@@ -2352,7 +2400,7 @@ app.filter('unavailableHalDeviceId', function (bridgeService) {
|
||||
if(input === undefined || input === null || input.length === undefined)
|
||||
return out;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if(input[i].mapType !== null && bridgeService.aContainsB(input[i].mapType, "hal")){
|
||||
if(input[i].mapType !== undefined && input[i].mapType !== null && bridgeService.aContainsB(input[i].mapType, "hal")){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
@@ -2366,7 +2414,7 @@ app.filter('configuredButtons', function () {
|
||||
if(input === undefined || input === null || input.length === undefined)
|
||||
return out;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if(input[i].mapType === "harmonyButton"){
|
||||
if(input[i].mapType !== undefined && input[i].mapType === "harmonyButton"){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
@@ -2380,7 +2428,7 @@ app.filter('configuredMqttMsgs', function () {
|
||||
if(input === undefined || input === null || input.length === undefined)
|
||||
return out;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if(input[i].mapType === "mqttMessage"){
|
||||
if(input[i].mapType !== undefined && input[i].mapType === "mqttMessage"){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
@@ -2408,7 +2456,7 @@ app.filter('unavailableHassDeviceId', function (bridgeService) {
|
||||
if(input === undefined || input === null || input.length === undefined)
|
||||
return out;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if(input[i].mapType !== null && bridgeService.aContainsB(input[i].mapType, "hass")){
|
||||
if(input[i].mapType !== undefined && input[i].mapType !== null && bridgeService.aContainsB(input[i].mapType, "hass")){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="id">ID</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorUniqueId">ID</th>
|
||||
<th sortable-header col="name">Name</th>
|
||||
<th sortable-header col="deviceType">Type</th>
|
||||
<th sortable-header col="targetDevice">Target</th>
|
||||
@@ -72,7 +72,7 @@
|
||||
<div class="panel-heading">
|
||||
<h1 class="panel-title">
|
||||
Bridge Device DB Backup <a ng-click="toggleBk()"><span
|
||||
class={{imgBkUrl}} aria-hidden="true"></a>
|
||||
class={{imgBkUrl}} aria-hidden="true"></span></a>
|
||||
</h1>
|
||||
</div>
|
||||
<div ng-if="visibleBk" class="animate-if" class="panel-body">
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="name">Name</th>
|
||||
<th sortable-header col="id">Id</th>
|
||||
<th sortable-header col="hub">Hub</th>
|
||||
<th sortable-header col="label" comparator-fn="comparatorLabel">Name</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorNumber">Id</th>
|
||||
<th sortable-header col="hub" comparator-fn="comparatorHub">Hub</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="name">Name</th>
|
||||
<th sortable-header col="id">Id</th>
|
||||
<th sortable-header col="hub">Hub</th>
|
||||
<th sortable-header col="label" comparator-fn="comparatorLabel">Name</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorNumber">Id</th>
|
||||
<th sortable-header col="hub" comparator-fn="comparatorHub">Hub</th>
|
||||
<th>On Button</th>
|
||||
<th>Off Button</th>
|
||||
<th>Actions</th>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
value="{{selectAll}}"
|
||||
ng-checked="selectAll"
|
||||
ng-click="toggleSelectAll()"> Name</span></th>
|
||||
<th sortable-header col="id">Id</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorUniqueId">Id</th>
|
||||
<th sortable-header col="category">Category</th>
|
||||
<th sortable-header col="room">Room</th>
|
||||
<th sortable-header col="veraname">Vera</th>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="name">Name</th>
|
||||
<th sortable-header col="id">Id</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorUniqueId">Id</th>
|
||||
<th sortable-header col="room">Room</th>
|
||||
<th sortable-header col="veraname">Vera</th>
|
||||
<th>Actions</th>
|
||||
|
||||
Reference in New Issue
Block a user