Updated upnp response for M-SEARCH again. Updated devices to have

numbering more in line with how the hue bridge is done. Added special
generation of hue device unique id as the philips api spec shows.  Added
a renumber function to convert id's.
This commit is contained in:
Admin
2016-09-28 16:18:53 -05:00
parent 4da5f65d89
commit 8ff7bc0120
9 changed files with 115 additions and 9 deletions

View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId>
<version>3.1.0b</version>
<version>3.1.0c</version>
<packaging>jar</packaging>
<name>HA Bridge</name>

View File

@@ -84,7 +84,7 @@ public class DeviceResponse {
response.setState(device.getDeviceState());
response.setName(device.getName());
response.setUniqueid(device.getId());
response.setUniqueid(device.getUniqueid());
response.setManufacturername("Philips");
response.setType("Dimmable light");
response.setModelid("LWB004");

View File

@@ -11,6 +11,9 @@ public class DeviceDescriptor{
@SerializedName("id")
@Expose
private String id;
@SerializedName("uniqueid")
@Expose
private String uniqueid;
@SerializedName("name")
@Expose
private String name;
@@ -128,6 +131,14 @@ public class DeviceDescriptor{
this.id = id;
}
public String getUniqueid() {
return uniqueid;
}
public void setUniqueid(String uniqueid) {
this.uniqueid = uniqueid;
}
public String getHeaders() {
return headers;
}

View File

@@ -2,6 +2,7 @@ package com.bwssystems.HABridge.dao;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -9,8 +10,11 @@ import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import javax.xml.bind.DatatypeConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,7 +33,7 @@ public class DeviceRepository extends BackupHandler {
private Map<String, DeviceDescriptor> devices;
private Path repositoryPath;
private Gson gson;
final private Random random = new Random();
private Integer maxId;
private Logger log = LoggerFactory.getLogger(DeviceRepository.class);
public DeviceRepository(String deviceDb) {
@@ -41,6 +45,7 @@ public class DeviceRepository extends BackupHandler {
repositoryPath = null;
repositoryPath = Paths.get(deviceDb);
setupParams(repositoryPath, ".bk", "device.db-");
maxId = 1;
_loadRepository(repositoryPath);
}
@@ -57,6 +62,9 @@ public class DeviceRepository extends BackupHandler {
DeviceDescriptor list[] = gson.fromJson(jsonContent, DeviceDescriptor[].class);
for(int i = 0; i < list.length; i++) {
put(list[i].getId(), list[i]);
if(Integer.decode(list[i].getId()) > maxId) {
maxId = Integer.decode(list[i].getId());
}
}
}
}
@@ -84,8 +92,17 @@ public class DeviceRepository extends BackupHandler {
for(int i = 0; i < descriptors.length; i++) {
if(descriptors[i].getId() != null && descriptors[i].getId().length() > 0)
devices.remove(descriptors[i].getId());
else
descriptors[i].setId(String.valueOf(random.nextInt(Integer.MAX_VALUE)));
else {
descriptors[i].setId(String.valueOf(maxId));
maxId++;
}
if(descriptors[i].getUniqueid() == null || descriptors[i].getUniqueid().length() == 0) {
BigInteger bigInt = BigInteger.valueOf(Integer.decode(descriptors[i].getId()));
byte[] theBytes = bigInt.toByteArray();
String hexValue = DatatypeConverter.printHexBinary(theBytes);
descriptors[i].setUniqueid("00:17:88:5E:D3:" + hexValue + "-" + hexValue);
}
put(descriptors[i].getId(), descriptors[i]);
theNames = theNames + " " + descriptors[i].getName() + ", ";
}
@@ -94,6 +111,28 @@ public class DeviceRepository extends BackupHandler {
log.debug("Save device(s): " + theNames);
}
public void renumber() {
List<DeviceDescriptor> list = new ArrayList<DeviceDescriptor>(devices.values());
Iterator<DeviceDescriptor> deviceIterator = list.iterator();
Map<String, DeviceDescriptor> newdevices = new HashMap<String, DeviceDescriptor>();;
maxId = 1;
log.debug("Renumber devices.");
while(deviceIterator.hasNext()) {
DeviceDescriptor theDevice = deviceIterator.next();
theDevice.setId(String.valueOf(maxId));
BigInteger bigInt = BigInteger.valueOf(maxId);
byte[] theBytes = bigInt.toByteArray();
String hexValue = DatatypeConverter.printHexBinary(theBytes);
theDevice.setUniqueid("00:17:88:5E:D3:" + hexValue + "-" + hexValue);
newdevices.put(theDevice.getId(), theDevice);
maxId++;
}
devices = newdevices;
String jsonValue = gson.toJson(findAll());
repositoryWriter(jsonValue, repositoryPath);
}
public String delete(DeviceDescriptor aDescriptor) {
if (aDescriptor != null) {
devices.remove(aDescriptor.getId());

View File

@@ -8,6 +8,7 @@ import static spark.Spark.delete;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -280,6 +281,21 @@ public class DeviceResource {
return halHome.getDevices();
}, new JsonTransformer());
// http://ip_address:port/api/devices/exec/renumber CORS request
options(API_CONTEXT + "/exec/renumber", "application/json", (request, response) -> {
response.status(HttpStatus.SC_OK);
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
response.header("Access-Control-Allow-Methods", "POST");
response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers"));
response.header("Content-Type", "text/html; charset=utf-8");
return "";
});
post (API_CONTEXT + "/exec/renumber", "application/json", (request, response) -> {
log.debug("Renumber devices.");
deviceRepository.renumber();
return null;
}, new JsonTransformer());
get (API_CONTEXT + "/backup/available", "application/json", (request, response) -> {
log.debug("Get backup filenames");
response.status(HttpStatus.SC_OK);

View File

@@ -6,7 +6,7 @@ import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.BridgeControlDescriptor;
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
import com.bwssystems.HABridge.Configuration;
import com.bwssystems.HABridge.api.hue.HuePublicConfig;
// import com.bwssystems.HABridge.api.hue.HuePublicConfig;
import java.io.IOException;
import java.net.*;
@@ -24,6 +24,14 @@ public class UpnpListener {
private boolean traceupnp;
private BridgeControlDescriptor bridgeControl;
private boolean discoveryTemplateLatest;
private String discoveryTemplate = "HTTP/1.1 200 OK\r\n" +
"CACHE-CONTROL: max-age=86400\r\n" +
"EXT:\r\n" +
"LOCATION: http://%s:%s/description.xml\r\n" +
"SERVER: FreeRTOS/7.4.2 UPnP/1.0 IpBridge/1.10.0\r\n" +
"ST: upnp:rootdevice\r\n" +
"USN: uuid:2f402f80-da50-11e1-9b23-001788102201\r\n\r\n";
/*
private String discoveryTemplate = "HTTP/1.1 200 OK\r\n" +
"HOST: %s:%s\r\n" +
"CACHE-CONTROL: max-age=86400\r\n" +
@@ -33,6 +41,9 @@ public class UpnpListener {
"hue-bridgeid: %s\r\n" +
"ST: upnp:rootdevice\r\n" +
"USN: uuid:2f402f80-da50-11e1-9b23-001788102201\r\n\r\n";
discoveryResponse = String.format(discoveryTemplate, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, HuePublicConfig.createConfig("temp", responseAddress).getBridgeid());
*/
private String discoveryTemplate091516 = "HTTP/1.1 200 OK\r\n" +
"CACHE-CONTROL: max-age=86400\r\n" +
"EXT:\r\n" +
@@ -40,6 +51,7 @@ public class UpnpListener {
"SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.10.0\r\n" +
"ST: urn:schemas-upnp-org:device:basic:1\r\n" +
"USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1\r\n\r\n";
/*
private String discoveryTemplateOld = "HTTP/1.1 200 OK\r\n" +
"CACHE-CONTROL: max-age=86400\r\n" +
"EXT:\r\n" +
@@ -48,7 +60,7 @@ public class UpnpListener {
"01-NLS: %s\r\n" +
"ST: urn:schemas-upnp-org:device:basic:1\r\n" +
"USN: uuid:Socket-1_0-221438K0100073::urn:Belkin:device:**\r\n\r\n";
*/
public UpnpListener(BridgeSettingsDescriptor theSettings, BridgeControlDescriptor theControl) {
super();
upnpResponsePort = theSettings.getUpnpResponsePort();
@@ -225,7 +237,7 @@ public class UpnpListener {
protected void sendUpnpResponse(DatagramSocket socket, InetAddress requester, int sourcePort) throws IOException {
String discoveryResponse = null;
if(discoveryTemplateLatest)
discoveryResponse = String.format(discoveryTemplate, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, HuePublicConfig.createConfig("temp", responseAddress).getBridgeid());
discoveryResponse = String.format(discoveryTemplate, responseAddress, httpServerPort);
else
discoveryResponse = String.format(discoveryTemplate091516, responseAddress, httpServerPort);
if(traceupnp) {

View File

@@ -115,12 +115,24 @@ app.service('bridgeService', function ($http, $window, ngToast) {
);
};
this.renumberDevices = function () {
return $http.post(this.state.base + "/exec/renumber").then(
function (response) {
self.viewDevices();
},
function (error) {
self.displayError("Cannot renumber devices from habridge: ", error);
}
);
};
this.clearDevice = function () {
if(self.state.device == null)
self.state.device = [];
self.state.device.id = "";
self.state.device.mapType = null;
self.state.device.mapId = null;
self.state.device.uniqueid = null;
self.state.device.name = "";
self.state.device.onUrl = "";
self.state.device.dimUrl = "";
@@ -785,6 +797,9 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
bridgeService.editDevice(device);
$location.path('/editdevice');
};
$scope.renumberDevices = function() {
bridgeService.renumberDevices();
};
$scope.backupDeviceDb = function (optionalbackupname) {
bridgeService.backupDeviceDb(optionalbackupname);
};

View File

@@ -25,6 +25,11 @@
<h2 class="panel-title">Current devices
({{bridge.devices.length}})</h2>
</div>
<form name="form">
<p>
<button class="btn btn-primary" type="submit" ng-click="renumberDevices()">Renumber Devices</button>
</p>
</form>
<scrollable-table watch="bridge.devices">
<table class="table table-bordered table-striped table-hover">
<thead>

View File

@@ -107,6 +107,14 @@
Clear Device</button>
</div>
</div>
<div class="form-group">
<label class="col-xs-12 col-sm-2 control-label" for="device-unique-id">Unique Id (used for Hue responses) </label>
<div class="col-xs-8 col-sm-7">
<input type="text" class="form-control" id="device-unique-id"
ng-model="device.uniqueid" placeholder="AA:BB:CC:DD:EE:FF-XX" readonly>
</div>
</div>
<div ng-if="device.mapType" class="form-group">
<label class="col-xs-12 col-sm-2 control-label" for="device-map-id">Map
ID </label>