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());
+ }
+}