diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Resource.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Resource.java index c41ce35f94e01..05e5f4ca2fa73 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Resource.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/Resource.java @@ -124,7 +124,7 @@ public Resource(@Nullable ResourceType resourceType) { /** * Check if light or grouped_light resource contains any * relevant fields to process according to its type. - * + * * As an example, {@link #colorTemperature} is relevant for a light * resource because it's needed for updating the color-temperature channels. * @@ -919,6 +919,11 @@ public Resource setType(ResourceType resourceType) { return this; } + public Resource setStatus(@Nullable JsonElement status) { + this.status = status; + return this; + } + @Override public String toString() { String id = this.id; diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/helper/Setters.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/helper/Setters.java index 35083b09e8f43..9a1a68a7a88d2 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/helper/Setters.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/api/dto/clip2/helper/Setters.java @@ -15,6 +15,7 @@ import java.math.BigDecimal; import java.time.Duration; import java.util.Collection; +import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -60,6 +61,16 @@ public class Setters { private static final Set LIGHT_TYPES = Set.of(ResourceType.LIGHT, ResourceType.GROUPED_LIGHT); + /* + * Comparator to sort Resources so that scene activation resources come last. + */ + private static final Comparator SCENE_ACTIVE_COMPARATOR = new Comparator<>() { + @Override + public int compare(Resource r1, Resource r2) { + return (r1.getSceneActive().orElse(false) ? 1 : 0) + (r2.getSceneActive().orElse(false) ? -1 : 0); + } + }; + /** * Setter for Alert field: * Use the given command value to set the target resource DTO value based on the attributes of the source resource @@ -398,7 +409,18 @@ public static Collection mergeLightResources(Collection reso iterator.remove(); } } + return resources; + } + /** + * Sort a list of resources so that scene activation event resources (if any) get + * processed after scene de-activation event resources (if any). + * + * @param resources list of resources to be sorted. + * @return the sorted list with scene activation event resources moved to the end. + */ + public static List sortSceneResources(List resources) { + resources.sort(SCENE_ACTIVE_COMPARATOR); return resources; } } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2BridgeHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2BridgeHandler.java index e6dd7181ea26a..98602854e45e1 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2BridgeHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/Clip2BridgeHandler.java @@ -535,6 +535,7 @@ private void onResourcesEventTask(List resources) { if (numberOfResources != resources.size()) { logger.debug("onResourcesEventTask() merged to {} resources", resources.size()); } + Setters.sortSceneResources(resources); getThing().getThings().forEach(thing -> { if (thing.getHandler() instanceof Clip2ThingHandler clip2ThingHandler) { resources.forEach(resource -> clip2ThingHandler.onResource(resource)); diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/clip2/SortSceneResourcesTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/clip2/SortSceneResourcesTest.java new file mode 100644 index 0000000000000..b09f07b1a3d3d --- /dev/null +++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/clip2/SortSceneResourcesTest.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hue.internal.clip2; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.hue.internal.api.dto.clip2.Resource; +import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType; +import org.openhab.binding.hue.internal.api.dto.clip2.helper.Setters; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; + +/** + * JUnit test for sorting the sequence of scene events in a list. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +class SortSceneResourcesTest { + + private static final JsonElement ACTIVE = JsonParser.parseString("{\"active\":\"static\"}"); + private static final JsonElement INACTIVE = JsonParser.parseString("{\"active\":\"inactive\"}"); + + @Test + void testSceneSorting() { + List list = new ArrayList<>(); + list.add(new Resource(ResourceType.LIGHT).setId("0")); + list.add(new Resource(ResourceType.SCENE).setId("1").setStatus(ACTIVE)); + list.add(new Resource(ResourceType.LIGHT).setId("2")); + list.add(new Resource(ResourceType.SCENE).setId("3").setStatus(INACTIVE)); + list.add(new Resource(ResourceType.LIGHT).setId("4")); + list.forEach(r -> r.markAsSparse()); + + assertEquals(5, list.size()); + assertEquals("0", list.get(0).getId()); + assertEquals("1", list.get(1).getId()); + assertEquals("2", list.get(2).getId()); + assertEquals("3", list.get(3).getId()); + assertEquals("4", list.get(4).getId()); + + assertTrue(list.get(1).getSceneActive().get()); + assertFalse(list.get(3).getSceneActive().get()); + + Setters.sortSceneResources(list); + + assertEquals(5, list.size()); + assertEquals("0", list.get(0).getId()); + assertEquals("2", list.get(1).getId()); + assertEquals("3", list.get(2).getId()); + assertEquals("4", list.get(3).getId()); + assertEquals("1", list.get(4).getId()); + + assertFalse(list.get(2).getSceneActive().get()); + assertTrue(list.get(4).getSceneActive().get()); + } +}