diff --git a/pom.xml b/pom.xml index 8f2546c..17c4999 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 3.1.0b + 3.1.0c jar HA Bridge diff --git a/src/main/java/com/bwssystems/HABridge/api/hue/DeviceResponse.java b/src/main/java/com/bwssystems/HABridge/api/hue/DeviceResponse.java index e293145..8d25c60 100644 --- a/src/main/java/com/bwssystems/HABridge/api/hue/DeviceResponse.java +++ b/src/main/java/com/bwssystems/HABridge/api/hue/DeviceResponse.java @@ -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"); diff --git a/src/main/java/com/bwssystems/HABridge/dao/DeviceDescriptor.java b/src/main/java/com/bwssystems/HABridge/dao/DeviceDescriptor.java index 6ed7b95..480ea57 100644 --- a/src/main/java/com/bwssystems/HABridge/dao/DeviceDescriptor.java +++ b/src/main/java/com/bwssystems/HABridge/dao/DeviceDescriptor.java @@ -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; } diff --git a/src/main/java/com/bwssystems/HABridge/dao/DeviceRepository.java b/src/main/java/com/bwssystems/HABridge/dao/DeviceRepository.java index 6dc7218..727c73e 100644 --- a/src/main/java/com/bwssystems/HABridge/dao/DeviceRepository.java +++ b/src/main/java/com/bwssystems/HABridge/dao/DeviceRepository.java @@ -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 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 list = new ArrayList(devices.values()); + Iterator deviceIterator = list.iterator(); + Map newdevices = new HashMap();; + 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()); diff --git a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java index cd0fdc6..e57b911 100644 --- a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java +++ b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java @@ -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); diff --git a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java index 436371c..c0cf521 100644 --- a/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java +++ b/src/main/java/com/bwssystems/HABridge/upnp/UpnpListener.java @@ -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) { diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index b6c2cf1..face627 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -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); }; diff --git a/src/main/resources/public/views/configuration.html b/src/main/resources/public/views/configuration.html index 5a7c61d..9541661 100644 --- a/src/main/resources/public/views/configuration.html +++ b/src/main/resources/public/views/configuration.html @@ -25,6 +25,11 @@

Current devices ({{bridge.devices.length}})

+
+

+ +

+
diff --git a/src/main/resources/public/views/editdevice.html b/src/main/resources/public/views/editdevice.html index d11e6ca..09339bc 100644 --- a/src/main/resources/public/views/editdevice.html +++ b/src/main/resources/public/views/editdevice.html @@ -107,6 +107,14 @@ Clear Device +
+ + +
+ +
+