diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/ConfigStore.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/ConfigStore.java index 374fa88bc..4f6b09de7 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/ConfigStore.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/ConfigStore.java @@ -15,10 +15,11 @@ package org.openhab.io.hueemulation.internal; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Collections; +import java.util.IllegalFormatException; import java.util.LinkedHashSet; import java.util.Map; -import java.util.Random; import java.util.Set; +import java.util.UUID; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -121,6 +122,8 @@ public class ConfigStore { private int highestAssignedHueID = 1; + private String hueIDPrefix = ""; + public ConfigStore() { scheduler = ThreadPoolManager.getScheduledPool(ThreadPoolManager.THREAD_POOL_NAME_COMMON); } @@ -147,7 +150,7 @@ public class ConfigStore { determineHighestAssignedHueID(); if (config.uuid.isEmpty()) { - config.uuid = getHueUUID(); + config.uuid = UUID.randomUUID().toString(); writeUUIDFuture = scheduler.schedule(() -> { logger.info("No unique ID assigned yet. Assigning {} and restarting...", config.uuid); WriteConfig.setUUID(configAdmin, config.uuid); @@ -158,19 +161,6 @@ public class ConfigStore { } } - private static String getHueUUID() { - // Hue API example is AA:BB:CC:DD:EE:FF:00:11-XX - // XX is generated from the item. - final Random r = new Random(); - int n = r.nextInt(255); - final StringBuilder uuid = new StringBuilder(String.format("%02X", n)); - for (int i = 0; i < 7; i++) { - n = r.nextInt(255); - uuid.append(String.format(":%02X", n)); - } - return uuid.toString(); - } - private @Nullable InetAddress byName(@Nullable String address) { if (address == null) { return null; @@ -246,6 +236,8 @@ public class ConfigStore { ds.config.bridgeid = ds.config.bridgeid.substring(0, 12); } + hueIDPrefix = getHueIDPrefixFromUUID(config.uuid); + if (config.permanentV1bridge) { ds.config.makeV1bridge(); } @@ -271,6 +263,32 @@ public class ConfigStore { } } + /** + * Get the prefix used to create a unique id + * + * @param uuid The uuid + * @return The prefix in the format of AA:BB:CC:DD:EE:FF:00:11 if uuid is a valid UUID, otherwise uuid is returned. + */ + private String getHueIDPrefixFromUUID(final String uuid) { + // Hue API example of a unique id is AA:BB:CC:DD:EE:FF:00:11-XX + // XX is generated from the item. + String prefix = uuid; + try { + // Generate prefix if uuid is a randomly generated UUID + if (UUID.fromString(uuid).version() == 4) { + final StringBuilder sb = new StringBuilder(23); + sb.append(uuid, 0, 2).append(":").append(uuid, 2, 4).append(":").append(uuid, 4, 6).append(":") + .append(uuid, 6, 8).append(":").append(uuid, 9, 11).append(":").append(uuid, 11, 13).append(":") + .append(uuid, 14, 16).append(":").append(uuid, 16, 18); + prefix = sb.toString().toUpperCase(); + } + } catch (final IllegalArgumentException e) { + // uuid is not a valid UUID + } + + return prefix; + } + @Deactivate public void deactive(int reason) { ScheduledFuture future = pairingOffFuture; @@ -324,7 +342,24 @@ public class ConfigStore { metadataRegistry.add(new Metadata(key, String.valueOf(hueId), null)); } - return String.format("%02X", hueId); + return String.valueOf(hueId); + } + + /** + * Get the unique id + * + * @param hueId The item hueID + * @return The unique id + */ + public String getHueUniqueId(final String hueId) { + String unique = hueId; + try { + unique = String.format("%02X", Integer.valueOf(hueId)); + } catch (final NumberFormatException | IllegalFormatException e) { + // Use the hueId as is + } + + return hueIDPrefix + "-" + unique; } public boolean isReady() { diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroups.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroups.java index 2e28f852d..57087082e 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroups.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroups.java @@ -180,7 +180,7 @@ public class LightsAndGroups implements RegistryChangeListener { cs.ds.groups.put(hueID, group); } else { - HueLightEntry device = new HueLightEntry(element, cs.ds.config.uuid + "-" + hueID.toString(), deviceType); + HueLightEntry device = new HueLightEntry(element, cs.getHueUniqueId(hueID), deviceType); device.item = element; cs.ds.lights.put(hueID, device); updateGroup0(); diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/ItemUIDtoHueIDMappingTests.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/ItemUIDtoHueIDMappingTests.java index 9b017e6be..bfa5da42b 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/ItemUIDtoHueIDMappingTests.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/ItemUIDtoHueIDMappingTests.java @@ -88,7 +88,7 @@ public class ItemUIDtoHueIDMappingTests { itemRegistry.add(item); String hueID = cs.mapItemUIDtoHueID(item); - assertThat(hueID, CoreMatchers.is("02")); + assertThat(hueID, CoreMatchers.is("2")); HueLightEntry device = cs.ds.lights.get(hueID); assertThat(device.item, is(item)); @@ -108,7 +108,7 @@ public class ItemUIDtoHueIDMappingTests { itemRegistry.add(item); String hueID = cs.mapItemUIDtoHueID(item); - assertThat(hueID, CoreMatchers.is("0A")); + assertThat(hueID, CoreMatchers.is("10")); HueLightEntry device = cs.ds.lights.get(hueID); assertThat(device.item, is(item));