diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/config/HueBridgeConfig.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/config/HueBridgeConfig.java index 6294207ba..dfa92a798 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/config/HueBridgeConfig.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/config/HueBridgeConfig.java @@ -14,10 +14,9 @@ package org.openhab.binding.hue.internal.config; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.hue.internal.handler.HueBridgeHandler; /** - * Configuration for the {@link HueBridgeHandler}. + * Configuration for the {@link org.openhab.binding.hue.internal.handler.HueBridgeHandler}. * * @author Christoph Weitkamp - Initial contribution */ diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java index 58536ccd0..650af07aa 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/connection/HueBridge.java @@ -996,7 +996,12 @@ public class HueBridge { // Methods that convert gson exceptions into ApiExceptions private T safeFromJson(String json, Type typeOfT) throws ApiException { try { - return gson.fromJson(json, typeOfT); + @Nullable + T safe = gson.fromJson(json, typeOfT); + if (safe == null) { + throw new ApiException("JSON is null or empty"); + } + return safe; } catch (JsonParseException e) { throw new ApiException("API returned unexpected result: " + e.getMessage()); } @@ -1004,7 +1009,12 @@ public class HueBridge { private T safeFromJson(String json, Class classOfT) throws ApiException { try { - return gson.fromJson(json, classOfT); + @Nullable + T safe = gson.fromJson(json, classOfT); + if (safe == null) { + throw new ApiException("JSON is null or empty"); + } + return safe; } catch (JsonParseException e) { throw new ApiException("API returned unexpected result: " + e.getMessage()); } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/BridgeJsonParameters.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/BridgeJsonParameters.java index eeb842b56..b109cbe6f 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/BridgeJsonParameters.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/BridgeJsonParameters.java @@ -12,6 +12,9 @@ */ package org.openhab.binding.hue.internal.discovery; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + import com.google.gson.annotations.SerializedName; /** @@ -22,15 +25,17 @@ import com.google.gson.annotations.SerializedName; * @author Awelkiyar Wehabrebi - Initial contribution and API * @author Christoph Knauf - Refactorings */ +@NonNullByDefault public class BridgeJsonParameters { - private String id; + private @Nullable String id; @SerializedName("internalipaddress") - private String internalIpAddress; + private @Nullable String internalIpAddress; @SerializedName("macaddress") - private String macAddress; - private String name; + private @Nullable String macAddress; + private @Nullable String name; + @SuppressWarnings("unused") private BridgeJsonParameters() { // This no arguments constructor is required for Gson deserialization } @@ -42,19 +47,19 @@ public class BridgeJsonParameters { this.name = name; } - public String getInternalIpAddress() { + public @Nullable String getInternalIpAddress() { return internalIpAddress; } - public String getId() { + public @Nullable String getId() { return id; } - public String getMacAddress() { + public @Nullable String getMacAddress() { return macAddress; } - public String getName() { + public @Nullable String getName() { return name; } } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscovery.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscovery.java index c4ce4769b..9c3f3e3e7 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscovery.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscovery.java @@ -80,36 +80,44 @@ public class HueBridgeNupnpDiscovery extends AbstractDiscoveryService { */ private void discoverHueBridges() { for (BridgeJsonParameters bridge : getBridgeList()) { - if (isReachableAndValidHueBridge(bridge)) { - String host = bridge.getInternalIpAddress(); - String serialNumber = bridge.getId().toLowerCase(); - ThingUID uid = new ThingUID(THING_TYPE_BRIDGE, serialNumber); - ThingUID legacyUID = null; - String label = String.format(DISCOVERY_LABEL_PATTERN, host); - - if (isClip2Supported(host)) { - legacyUID = uid; - uid = new ThingUID(THING_TYPE_BRIDGE_API2, serialNumber); - Optional legacyThingOptional = getLegacyBridge(host); - if (legacyThingOptional.isPresent()) { - Thing legacyThing = legacyThingOptional.get(); - String label2 = legacyThing.getLabel(); - label = Objects.nonNull(label2) ? label2 : label; - } - } - - DiscoveryResultBuilder builder = DiscoveryResultBuilder.create(uid) // - .withLabel(label) // - .withProperty(HOST, host) // - .withProperty(Thing.PROPERTY_SERIAL_NUMBER, serialNumber) // - .withRepresentationProperty(Thing.PROPERTY_SERIAL_NUMBER); - - if (Objects.nonNull(legacyUID)) { - builder.withProperty(PROPERTY_LEGACY_THING_UID, legacyUID.getAsString()); - } - - thingDiscovered(builder.build()); + if (!isReachableAndValidHueBridge(bridge)) { + continue; } + String host = bridge.getInternalIpAddress(); + if (host == null) { + continue; + } + String id = bridge.getId(); + if (id == null) { + continue; + } + String serialNumber = id.toLowerCase(); + ThingUID uid = new ThingUID(THING_TYPE_BRIDGE, serialNumber); + ThingUID legacyUID = null; + String label = String.format(DISCOVERY_LABEL_PATTERN, host); + + if (isClip2Supported(host)) { + legacyUID = uid; + uid = new ThingUID(THING_TYPE_BRIDGE_API2, serialNumber); + Optional legacyThingOptional = getLegacyBridge(host); + if (legacyThingOptional.isPresent()) { + Thing legacyThing = legacyThingOptional.get(); + String label2 = legacyThing.getLabel(); + label = Objects.nonNull(label2) ? label2 : label; + } + } + + DiscoveryResultBuilder builder = DiscoveryResultBuilder.create(uid) // + .withLabel(label) // + .withProperty(HOST, host) // + .withProperty(Thing.PROPERTY_SERIAL_NUMBER, serialNumber) // + .withRepresentationProperty(Thing.PROPERTY_SERIAL_NUMBER); + + if (Objects.nonNull(legacyUID)) { + builder.withProperty(PROPERTY_LEGACY_THING_UID, legacyUID.getAsString()); + } + + thingDiscovered(builder.build()); } } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeUPNPDiscoveryParticipant.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeUPNPDiscoveryParticipant.java index 27f70c21f..f607bd25e 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeUPNPDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeUPNPDiscoveryParticipant.java @@ -32,7 +32,6 @@ import org.openhab.core.config.discovery.DiscoveryResult; import org.openhab.core.config.discovery.DiscoveryResultBuilder; import org.openhab.core.config.discovery.DiscoveryService; import org.openhab.core.config.discovery.upnp.UpnpDiscoveryParticipant; -import org.openhab.core.config.discovery.upnp.internal.UpnpDiscoveryService; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingUID; @@ -45,7 +44,7 @@ import org.slf4j.LoggerFactory; /** * The {@link HueBridgeUPNPDiscoveryParticipant} is responsible for discovering new and removed Hue Bridges. It uses the - * central {@link UpnpDiscoveryService}. + * central {@link org.openhab.core.config.discovery.upnp.internal.UpnpDiscoveryService}. * * The discovery through UPnP was replaced by mDNS discovery for recent bridges (V2). * For old bridges (V1), the UPnP discovery is still required (as mDNS is not implemented). diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ApiVersion.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ApiVersion.java index a4c6dc738..21b1a4007 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ApiVersion.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/ApiVersion.java @@ -12,7 +12,6 @@ */ package org.openhab.binding.hue.internal.dto; -import java.util.Comparator; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -77,7 +76,7 @@ public class ApiVersion { } /** - * compare API versions according to {@link Comparator#compare(Object, Object)} + * compare API versions according to {@link java.util.Comparator#compare(Object, Object)} * * @param other * @return diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Config.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Config.java index 01f669507..1e67ff79b 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Config.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Config.java @@ -17,6 +17,8 @@ import java.util.Date; import java.util.List; import java.util.Map; +import com.google.gson.annotations.SerializedName; + /** * Detailed bridge info available if authenticated. * @@ -37,7 +39,8 @@ public class Config { private String gateway; private String proxyaddress; private int proxyport; - private Date UTC; + @SerializedName("UTC") + private Date utc; private boolean linkbutton; private Map whitelist; private SoftwareUpdate swupdate; @@ -150,7 +153,7 @@ public class Config { * @return time on the bridge */ public Date getUTCTime() { - return UTC; + return utc; } /** diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullConfig.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullConfig.java index 88aab7ec1..7e23c6332 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullConfig.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullConfig.java @@ -35,8 +35,9 @@ public class FullConfig { public List getLights() { ArrayList lightsList = new ArrayList<>(); - for (String id : lights.keySet()) { - FullLight light = lights.get(id); + for (Map.Entry entry : lights.entrySet()) { + String id = entry.getKey(); + FullLight light = entry.getValue(); light.setId(id); lightsList.add(light); } @@ -52,8 +53,9 @@ public class FullConfig { public List getGroups() { ArrayList groupsList = new ArrayList<>(); - for (String id : groups.keySet()) { - FullGroup group = groups.get(id); + for (Map.Entry entry : groups.entrySet()) { + String id = entry.getKey(); + FullGroup group = entry.getValue(); group.setId(id); groupsList.add(group); } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullGroup.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullGroup.java index 2f984c99f..2bdd1df35 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullGroup.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullGroup.java @@ -13,9 +13,13 @@ package org.openhab.binding.hue.internal.dto; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + import com.google.gson.reflect.TypeToken; /** @@ -25,13 +29,14 @@ import com.google.gson.reflect.TypeToken; * @author Denis Dudnik - moved Jue library source code inside the smarthome Hue binding * @author Laurent Garnier - field state added */ +@NonNullByDefault public class FullGroup extends Group { public static final Type GSON_TYPE = new TypeToken>() { }.getType(); - private State action; - private List lights; - private State groupState; // Will not be set by hue API + private @Nullable State action; + private @Nullable List lights; + private @Nullable State groupState; // Will not be set by hue API FullGroup() { super(); @@ -53,7 +58,7 @@ public class FullGroup extends Group { * * @return last state update */ - public State getAction() { + public @Nullable State getAction() { return action; } @@ -63,7 +68,8 @@ public class FullGroup extends Group { * @return lights in the group */ public List getLightIds() { - return lights; + List lights = this.lights; + return lights != null ? lights : new ArrayList<>(); } /** @@ -72,6 +78,10 @@ public class FullGroup extends Group { * @return current state */ public State getState() { + State groupState = this.groupState; + if (groupState == null) { + throw new IllegalStateException("Group state not initialized when requested"); + } return groupState; } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullHueObject.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullHueObject.java index 0aae94e1d..8189fb695 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullHueObject.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/FullHueObject.java @@ -67,6 +67,7 @@ public class FullHueObject extends HueObject { } public @Nullable String getNormalizedModelID() { + String modelid = this.modelid; return modelid != null ? modelid.replaceAll(NORMALIZE_ID_REGEX, "_") : modelid; } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Scene.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Scene.java index 61ec343c5..ee13d71ac 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Scene.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/Scene.java @@ -13,6 +13,7 @@ package org.openhab.binding.hue.internal.dto; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -36,7 +37,7 @@ public class Scene { private @NonNullByDefault({}) String id; private @NonNullByDefault({}) String name; @SerializedName("lights") - private @NonNullByDefault({}) List lightIds; + private @Nullable List lightIds; @SerializedName("group") private @Nullable String groupId; private boolean recycle; @@ -84,7 +85,8 @@ public class Scene { * @return list of lights that the scene applies to */ public List getLightIds() { - return lightIds; + List lightIds = this.lightIds; + return lightIds != null ? lightIds : new ArrayList(); } /** @@ -141,11 +143,11 @@ public class Scene { * */ public boolean isApplicableTo(FullGroup group) { - if (getGroupId() == null) { + String groupId = this.groupId; + if (groupId == null) { return getLightIds().stream().allMatch(id -> group.getLightIds().contains(id)); } else { - String groupId = getGroupId(); - return groupId != null ? group.getId().contentEquals(groupId) : false; + return group.getId().contentEquals(groupId); } } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SearchForLightsRequest.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SearchForLightsRequest.java index 382cedd38..91174e678 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SearchForLightsRequest.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SearchForLightsRequest.java @@ -14,22 +14,23 @@ package org.openhab.binding.hue.internal.dto; import java.util.List; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * * @author Q42 - Initial contribution * @author Andre Fuechsel - search for lights with given serial number added * @author Denis Dudnik - moved Jue library source code inside the smarthome Hue binding */ -@SuppressWarnings("unused") +@NonNullByDefault public class SearchForLightsRequest { + @SuppressWarnings("unused") private List deviceid; public SearchForLightsRequest(List deviceid) { - if (deviceid != null && (deviceid.isEmpty() || deviceid.size() > 16)) { + if (deviceid.isEmpty() || deviceid.size() > 16) { throw new IllegalArgumentException("Group cannot be empty and cannot have more than 16 lights"); } - if (deviceid != null) { - this.deviceid = deviceid; - } + this.deviceid = deviceid; } } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SetAttributesRequest.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SetAttributesRequest.java index f15eb995f..09ae2c155 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SetAttributesRequest.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/dto/SetAttributesRequest.java @@ -13,7 +13,6 @@ package org.openhab.binding.hue.internal.dto; import java.util.List; -import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -45,6 +44,6 @@ public class SetAttributesRequest { } this.name = name; - this.lights = lights == null ? null : lights.stream().map(l -> l.getId()).collect(Collectors.toList()); + this.lights = lights == null ? null : lights.stream().map(l -> l.getId()).toList(); } } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java index 2f37def51..db6c6f29c 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java @@ -235,7 +235,7 @@ public class HueBridgeHandler extends ConfigStatusBridgeHandler implements HueCl sensorStatusListener.onSensorRemoved(); } - if (discovery != null && sensor != null) { + if (discovery != null) { discovery.removeSensorDiscovery(sensor); } }); @@ -295,7 +295,7 @@ public class HueBridgeHandler extends ConfigStatusBridgeHandler implements HueCl lightStatusListener.onLightRemoved(); } - if (discovery != null && light != null) { + if (discovery != null) { discovery.removeLightDiscovery(light); } }); @@ -385,7 +385,7 @@ public class HueBridgeHandler extends ConfigStatusBridgeHandler implements HueCl groupStatusListener.onGroupRemoved(); } - if (discovery != null && group != null) { + if (discovery != null) { discovery.removeGroupDiscovery(group); } }); @@ -402,12 +402,11 @@ public class HueBridgeHandler extends ConfigStatusBridgeHandler implements HueCl private void setBridgeSceneChannelStateOptions(List scenes, Map groups) { Map groupNames = groups.entrySet().stream() .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getName())); - List stateOptions = scenes.stream().map(scene -> scene.toStateOption(groupNames)) - .collect(Collectors.toList()); + List stateOptions = scenes.stream().map(scene -> scene.toStateOption(groupNames)).toList(); stateDescriptionOptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), CHANNEL_SCENE), stateOptions); consoleScenesList = scenes.stream().map(scene -> "Id is \"" + scene.getId() + "\" for scene \"" - + scene.toStateOption(groupNames).getLabel() + "\"").collect(Collectors.toList()); + + scene.toStateOption(groupNames).getLabel() + "\"").toList(); } }; diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java index 2424de2c5..118edaef3 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java @@ -455,11 +455,11 @@ public class HueGroupHandler extends BaseThingHandler implements HueLightActions FullGroup group = handler.getGroupById(groupId); if (group != null) { stateOptions = updatedScenes.stream().filter(scene -> scene.isApplicableTo(group)) - .map(Scene::toStateOption).collect(Collectors.toList()); - consoleScenesList = updatedScenes - .stream().filter(scene -> scene.isApplicableTo(group)).map(scene -> "Id is \"" + scene.getId() - + "\" for scene \"" + scene.toStateOption().getLabel() + "\"") - .collect(Collectors.toList()); + .map(Scene::toStateOption).toList(); + consoleScenesList = updatedScenes.stream().filter(scene -> scene.isApplicableTo(group)) + .map(scene -> "Id is \"" + scene.getId() + "\" for scene \"" + scene.toStateOption().getLabel() + + "\"") + .toList(); } } stateDescriptionOptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), CHANNEL_SCENE), diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionProvider.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionProvider.java index a185aeb2c..3ade2674c 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionProvider.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueStateDescriptionProvider.java @@ -58,6 +58,7 @@ public class HueStateDescriptionProvider extends BaseDynamicStateDescriptionProv StateDescriptionFragment oldStateDescriptionFragment = stateDescriptionFragments.get(channelUID); if (!stateDescriptionFragment.equals(oldStateDescriptionFragment)) { stateDescriptionFragments.put(channelUID, stateDescriptionFragment); + ItemChannelLinkRegistry itemChannelLinkRegistry = this.itemChannelLinkRegistry; postEvent(ThingEventFactory.createChannelDescriptionChangedEvent(channelUID, itemChannelLinkRegistry != null ? itemChannelLinkRegistry.getLinkedItemNames(channelUID) : Set.of(), stateDescriptionFragment, oldStateDescriptionFragment)); diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java index d59370a64..36689d828 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java @@ -30,6 +30,7 @@ import org.openhab.core.library.types.PercentType; import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.StringType; import org.openhab.core.library.unit.Units; +import org.openhab.core.util.ColorUtil; /** * The {@link LightStateConverter} is responsible for mapping to/from jue types. @@ -276,7 +277,7 @@ public class LightStateConverter { private static HSBType fromXYtoHSBType(State lightState) { float[] xy = lightState.getXY(); - HSBType hsb = HSBType.fromXY(xy[0], xy[1]); + HSBType hsb = ColorUtil.xyToHsb(new double[] { xy[0], xy[1] }); int brightnessInPercent = (int) Math.ceil(lightState.getBrightness() / BRIGHTNESS_FACTOR); brightnessInPercent = restrictToBounds(brightnessInPercent); diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/SceneTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/SceneTest.java index 1c341ce8d..3498c8570 100644 --- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/SceneTest.java +++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/SceneTest.java @@ -15,7 +15,6 @@ package org.openhab.binding.hue.internal; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; -import java.util.Arrays; import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -39,7 +38,7 @@ public class SceneTest { @Test public void testIsApplicableToHasGroupIdMatchingGroup() { String groupId = "groupId"; - List lights = Arrays.asList("1", "2"); + List lights = List.of("1", "2"); Scene scene = new Scene(PLACEHOLDER, PLACEHOLDER, groupId, lights, false); FullGroup group = new FullGroup(groupId, PLACEHOLDER, PLACEHOLDER, PLACEHOLDER_STATE, lights, @@ -56,8 +55,8 @@ public class SceneTest { public void testIsApplicableToHasGroupIdNotMatchingGroup() { String groupId = "groupId"; String otherGroupId = "otherGroupId"; - List lights = Arrays.asList("1", "2"); - List otherLights = Arrays.asList("1", "2", "3"); + List lights = List.of("1", "2"); + List otherLights = List.of("1", "2", "3"); Scene scene = new Scene(PLACEHOLDER, PLACEHOLDER, groupId, lights, false); @@ -76,8 +75,8 @@ public class SceneTest { */ @Test public void testIsApplicableToNoGroupIdSceneLightsContainedInGroup() { - List lights = Arrays.asList("1", "2"); - List moreLights = Arrays.asList("1", "2", "3"); + List lights = List.of("1", "2"); + List moreLights = List.of("1", "2", "3"); Scene scene = new Scene(PLACEHOLDER, PLACEHOLDER, null, lights, false); @@ -96,9 +95,9 @@ public class SceneTest { */ @Test public void testIsApplicableToNoGroupIdSceneLightsNotContainedInGroup() { - List lights = Arrays.asList("1", "2"); - List lessLights = Arrays.asList("1"); - List differentLights = Arrays.asList("3"); + List lights = List.of("1", "2"); + List lessLights = List.of("1"); + List differentLights = List.of("3"); Scene scene = new Scene(PLACEHOLDER, PLACEHOLDER, null, lights, false); diff --git a/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/AbstractHueOSGiTestParent.java b/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/AbstractHueOSGiTestParent.java index 2510bfdc9..133d86b60 100644 --- a/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/AbstractHueOSGiTestParent.java +++ b/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/AbstractHueOSGiTestParent.java @@ -14,13 +14,16 @@ package org.openhab.binding.hue.internal; import static org.junit.jupiter.api.Assertions.*; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.test.java.JavaOSGiTest; import org.openhab.core.thing.Thing; import org.openhab.core.thing.binding.ThingHandler; /** + * @author Markus Rathgeb - Initial contribution * @author Markus Rathgeb - migrated to plain Java test */ +@NonNullByDefault public class AbstractHueOSGiTestParent extends JavaOSGiTest { /** @@ -38,7 +41,7 @@ public class AbstractHueOSGiTestParent extends JavaOSGiTest { } else { assertNotNull(tmp); assertEquals(clazz, tmp.getClass()); - throw new RuntimeException(); + throw new IllegalStateException(); } }); } diff --git a/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/HueDeviceDiscoveryServiceOSGiTest.java b/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/HueDeviceDiscoveryServiceOSGiTest.java index 3e3776e4c..6be21f452 100644 --- a/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/HueDeviceDiscoveryServiceOSGiTest.java +++ b/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/HueDeviceDiscoveryServiceOSGiTest.java @@ -25,6 +25,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.http.HttpStatus; import org.junit.jupiter.api.AfterEach; @@ -61,16 +63,17 @@ import org.openhab.core.thing.binding.builder.ThingStatusInfoBuilder; * @author Denis Dudnik - switched to internally integrated source of Jue library * @author Markus Rathgeb - migrated to plain Java test */ +@NonNullByDefault public class HueDeviceDiscoveryServiceOSGiTest extends AbstractHueOSGiTestParent { - protected DiscoveryListener discoveryListener; - protected ThingRegistry thingRegistry; - protected Bridge hueBridge; - protected HueBridgeHandler hueBridgeHandler; - protected HueDeviceDiscoveryService discoveryService; + protected @Nullable DiscoveryListener discoveryListener; + protected @NonNullByDefault({}) ThingRegistry thingRegistry; + protected @NonNullByDefault({}) Bridge hueBridge; + protected @NonNullByDefault({}) HueBridgeHandler hueBridgeHandler; + protected @NonNullByDefault({}) HueDeviceDiscoveryService discoveryService; - protected final ThingTypeUID BRIDGE_THING_TYPE_UID = new ThingTypeUID("hue", "bridge"); - protected final ThingUID BRIDGE_THING_UID = new ThingUID(BRIDGE_THING_TYPE_UID, "testBridge"); + protected static final ThingTypeUID BRIDGE_THING_TYPE_UID = new ThingTypeUID("hue", "bridge"); + protected static final ThingUID BRIDGE_THING_UID = new ThingUID(BRIDGE_THING_TYPE_UID, "testBridge"); @BeforeEach public void setUp() { @@ -139,8 +142,8 @@ public class HueDeviceDiscoveryServiceOSGiTest extends AbstractHueOSGiTestParent } @Override - public Collection removeOlderResults(DiscoveryService source, long timestamp, - Collection thingTypeUIDs, ThingUID bridgeUID) { + public @Nullable Collection removeOlderResults(DiscoveryService source, long timestamp, + @Nullable Collection thingTypeUIDs, @Nullable ThingUID bridgeUID) { return null; } }); diff --git a/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscoveryOSGITest.java b/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscoveryOSGITest.java index 706f84414..164c287cc 100644 --- a/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscoveryOSGITest.java +++ b/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscoveryOSGITest.java @@ -26,7 +26,8 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openhab.core.config.discovery.DiscoveryListener; @@ -43,26 +44,31 @@ import org.openhab.core.thing.ThingUID; * @author Christoph Knauf - Initial contribution * @author Markus Rathgeb - migrated to plain Java test */ +@NonNullByDefault public class HueBridgeNupnpDiscoveryOSGITest extends JavaOSGiTest { - HueBridgeNupnpDiscovery sut; - VolatileStorageService volatileStorageService = new VolatileStorageService(); - DiscoveryListener discoveryListener; - Inbox inbox; + private @NonNullByDefault({}) HueBridgeNupnpDiscovery sut; + private VolatileStorageService volatileStorageService = new VolatileStorageService(); + private @Nullable DiscoveryListener discoveryListener; + private @NonNullByDefault({}) Inbox inbox; - final ThingTypeUID BRIDGE_THING_TYPE_UID = new ThingTypeUID("hue", "bridge"); - final String ip1 = "192.168.31.17"; - final String ip2 = "192.168.30.28"; - final String sn1 = "001788fffe20057f"; - final String sn2 = "001788fffe141b41"; - final ThingUID BRIDGE_THING_UID_1 = new ThingUID(BRIDGE_THING_TYPE_UID, sn1); - final ThingUID BRIDGE_THING_UID_2 = new ThingUID(BRIDGE_THING_TYPE_UID, sn2); - final String validBridgeDiscoveryResult = "[{\"id\":\"" + sn1 + "\",\"internalipaddress\":" + ip1 + "},{\"id\":\"" - + sn2 + "\",\"internalipaddress\":" + ip2 + "}]"; - String discoveryResult; - String expBridgeDescription = "{\"name\":\"Philips hue\",\"datastoreversion\":\"149\",\"swversion\":\"1957113050\",\"apiversion\":\"1.57.0\",\"mac\":\"00:11:22:33:44\",\"bridgeid\":\"$SN\",\"factorynew\":false,\"replacesbridgeid\":null,\"modelid\":\"BSB002\",\"starterkitid\":\"\"}"; + private static final ThingTypeUID BRIDGE_THING_TYPE_UID = new ThingTypeUID("hue", "bridge"); + private static final String IP1 = "192.168.31.17"; + private static final String IP2 = "192.168.30.28"; + private static final String SN1 = "001788fffe20057f"; + private static final String SN2 = "001788fffe141b41"; + private static final ThingUID BRIDGE_THING_UID_1 = new ThingUID(BRIDGE_THING_TYPE_UID, SN1); + private static final ThingUID BRIDGE_THING_UID_2 = new ThingUID(BRIDGE_THING_TYPE_UID, SN2); - private void checkDiscoveryResult(DiscoveryResult result, String expIp, String expSn) { + private final String validBridgeDiscoveryResult = "[{\"id\":\"" + SN1 + "\",\"internalipaddress\":" + IP1 + + "},{\"id\":\"" + SN2 + "\",\"internalipaddress\":" + IP2 + "}]"; + private @Nullable String discoveryResult; + private String expBridgeDescription = "{\"name\":\"Philips hue\",\"datastoreversion\":\"149\",\"swversion\":\"1957113050\",\"apiversion\":\"1.57.0\",\"mac\":\"00:11:22:33:44\",\"bridgeid\":\"$SN\",\"factorynew\":false,\"replacesbridgeid\":null,\"modelid\":\"BSB002\",\"starterkitid\":\"\"}"; + + private void checkDiscoveryResult(@Nullable DiscoveryResult result, String expIp, String expSn) { + if (result == null) { + return; + } assertThat(result.getBridgeUID(), nullValue()); assertThat(result.getLabel(), is(String.format(DISCOVERY_LABEL_PATTERN, expIp))); assertThat(result.getProperties().get("ipAddress"), is(expIp)); @@ -88,19 +94,19 @@ public class HueBridgeNupnpDiscoveryOSGITest extends JavaOSGiTest { } @Override - protected String doGetRequest(String url) throws IOException { + protected @Nullable String doGetRequest(String url) throws IOException { if (url.contains("meethue")) { return discoveryResult; - } else if (url.contains(ip1)) { - return expBridgeDescription.replaceAll("$SN", sn1); - } else if (url.contains(ip2)) { - return expBridgeDescription.replaceAll("$SN", sn2); + } else if (url.contains(IP1)) { + return expBridgeDescription.replaceAll("$SN", SN1); + } else if (url.contains(IP2)) { + return expBridgeDescription.replaceAll("$SN", SN2); } throw new IOException(); } @Override - protected boolean isClip2Supported(@NonNull String ipAddress) { + protected boolean isClip2Supported(String ipAddress) { return false; } } @@ -147,8 +153,8 @@ public class HueBridgeNupnpDiscoveryOSGITest extends JavaOSGiTest { } @Override - public Collection removeOlderResults(DiscoveryService source, long timestamp, - Collection thingTypeUIDs, ThingUID bridgeUID) { + public @Nullable Collection removeOlderResults(DiscoveryService source, long timestamp, + @Nullable Collection thingTypeUIDs, @Nullable ThingUID bridgeUID) { return null; } }); @@ -158,9 +164,9 @@ public class HueBridgeNupnpDiscoveryOSGITest extends JavaOSGiTest { waitForAssert(() -> { assertThat(results.size(), is(2)); assertThat(results.get(BRIDGE_THING_UID_1), is(notNullValue())); - checkDiscoveryResult(results.get(BRIDGE_THING_UID_1), ip1, sn1); + checkDiscoveryResult(results.get(BRIDGE_THING_UID_1), IP1, SN1); assertThat(results.get(BRIDGE_THING_UID_2), is(notNullValue())); - checkDiscoveryResult(results.get(BRIDGE_THING_UID_2), ip2, sn2); + checkDiscoveryResult(results.get(BRIDGE_THING_UID_2), IP2, SN2); final List inboxResults = inbox.stream().filter(forThingTypeUID(BRIDGE_THING_TYPE_UID)) .collect(Collectors.toList()); @@ -195,8 +201,8 @@ public class HueBridgeNupnpDiscoveryOSGITest extends JavaOSGiTest { } @Override - public Collection removeOlderResults(DiscoveryService source, long timestamp, - Collection thingTypeUIDs, ThingUID bridgeUID) { + public @Nullable Collection removeOlderResults(DiscoveryService source, long timestamp, + @Nullable Collection thingTypeUIDs, @Nullable ThingUID bridgeUID) { return null; } }); @@ -254,7 +260,7 @@ public class HueBridgeNupnpDiscoveryOSGITest extends JavaOSGiTest { // invalid bridge description expBridgeDescription = ""; - discoveryResult = "[{\"id\":\"001788fffe20057f\",\"internalipaddress\":" + ip1 + "}]"; + discoveryResult = "[{\"id\":\"001788fffe20057f\",\"internalipaddress\":" + IP1 + "}]"; sut.startScan(); waitForAssert(() -> { assertThat(results.size(), is(0)); diff --git a/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandlerOSGiTest.java b/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandlerOSGiTest.java index fcebe7678..ef46aad7d 100644 --- a/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandlerOSGiTest.java +++ b/itests/org.openhab.binding.hue.tests/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandlerOSGiTest.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.lang.reflect.Field; import java.util.concurrent.ScheduledExecutorService; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jetty.client.HttpClient; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -50,15 +51,15 @@ import org.openhab.core.thing.ThingUID; * @author Michael Grammling - Initial contribution * @author Denis Dudnik - switched to internally integrated source of Jue library */ +@NonNullByDefault public class HueBridgeHandlerOSGiTest extends AbstractHueOSGiTestParent { private static final ThingTypeUID BRIDGE_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "bridge"); private static final String TEST_USER_NAME = "eshTestUser"; private static final String DUMMY_HOST = "1.2.3.4"; - private ThingRegistry thingRegistry; - - private ScheduledExecutorService scheduler; + private @NonNullByDefault({}) ThingRegistry thingRegistry; + private @NonNullByDefault({}) ScheduledExecutorService scheduler; @BeforeEach public void setUp() {