From d27146d6af05ae8123248cb9958c955f49608325 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 30 Mar 2025 04:29:43 -0400 Subject: [PATCH] [insteon] Improve modem db default controller group support (#18465) Signed-off-by: Jeremy Setton --- bundles/org.openhab.binding.insteon/README.md | 2 +- .../insteon/internal/device/InsteonScene.java | 6 +-- .../insteon/internal/device/LinkManager.java | 3 +- .../internal/device/database/LinkDB.java | 11 ++--- .../internal/device/database/ModemDB.java | 49 ++++++++++++++++--- .../src/main/resources/OH-INF/thing/scene.xml | 2 +- 6 files changed, 52 insertions(+), 21 deletions(-) diff --git a/bundles/org.openhab.binding.insteon/README.md b/bundles/org.openhab.binding.insteon/README.md index 2a1cda8304..07e724a70d 100644 --- a/bundles/org.openhab.binding.insteon/README.md +++ b/bundles/org.openhab.binding.insteon/README.md @@ -115,7 +115,7 @@ Likewise, for a device that wasn't accessible during the binding initialization | Parameter | Required | Description | | --------- | :------: | -------------------------------------------------------------------------------------------------------------------------- | -| group | Yes | Insteon scene group number between 2 and 254. It can be found in the scene detailed information in the Insteon mobile app. | +| group | Yes | Insteon scene group number between 0 and 255. It can be found in the scene detailed information in the Insteon mobile app. | ### `x10` diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonScene.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonScene.java index 9c314a5133..0fa278e868 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonScene.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonScene.java @@ -33,11 +33,11 @@ import org.slf4j.LoggerFactory; */ @NonNullByDefault public class InsteonScene implements Scene { - public static final int GROUP_MIN = 2; - public static final int GROUP_MAX = 254; + public static final int GROUP_MIN = 0; + public static final int GROUP_MAX = 255; // limit new scene group minimum to 25 matching the current Insteon app behavior public static final int GROUP_NEW_MIN = 25; - public static final int GROUP_NEW_MAX = 254; + public static final int GROUP_NEW_MAX = 255; private final Logger logger = LoggerFactory.getLogger(InsteonScene.class); diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/LinkManager.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/LinkManager.java index bace3722ec..b638dfd2c2 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/LinkManager.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/LinkManager.java @@ -38,7 +38,6 @@ import org.slf4j.LoggerFactory; @NonNullByDefault public class LinkManager implements PortListener { private static final int LINKING_TIMEOUT = 30000; // in milliseconds - private static final int DEFAULT_CONTROLLER_GROUP = 0; private static final int DEFAULT_RESPONDER_GROUP = 1; private final Logger logger = LoggerFactory.getLogger(LinkManager.class); @@ -93,7 +92,7 @@ public class LinkManager implements PortListener { public void link(@Nullable InsteonAddress address) { addLinkingRequest(LinkMode.RESPONDER, DEFAULT_RESPONDER_GROUP); - addLinkingRequest(LinkMode.CONTROLLER, DEFAULT_CONTROLLER_GROUP); + addLinkingRequest(LinkMode.CONTROLLER, modem.getDB().getDefaultControllerGroup()); start(address); } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/database/LinkDB.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/database/LinkDB.java index 2d4b12a370..506f9f461e 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/database/LinkDB.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/database/LinkDB.java @@ -24,7 +24,6 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.insteon.internal.device.InsteonAddress; import org.openhab.binding.insteon.internal.device.InsteonDevice; import org.openhab.binding.insteon.internal.device.InsteonModem; -import org.openhab.binding.insteon.internal.device.InsteonScene; import org.openhab.binding.insteon.internal.utils.HexUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,9 +50,9 @@ public class LinkDB { private final Logger logger = LoggerFactory.getLogger(LinkDB.class); - private InsteonDevice device; - private TreeMap records = new TreeMap<>(Collections.reverseOrder()); - private TreeMap changes = new TreeMap<>(Collections.reverseOrder()); + private final InsteonDevice device; + private final TreeMap records = new TreeMap<>(Collections.reverseOrder()); + private final TreeMap changes = new TreeMap<>(Collections.reverseOrder()); private DatabaseStatus status = DatabaseStatus.EMPTY; private int delta = -1; private int firstLocation = 0x0FFF; @@ -556,8 +555,8 @@ public class LinkDB { .filter(record -> record.isActive() && record.isResponder() && record.getAddress().equals(modem.getAddress()) && record.getComponentId() == componentId && record.getOnLevel() > 0) - .map(LinkDBRecord::getGroup).filter(InsteonScene::isValidGroup).map(Integer::valueOf).distinct() - .toList(); + .map(LinkDBRecord::getGroup).filter(modem.getDB()::isValidBroadcastGroup).map(Integer::valueOf) + .distinct().toList(); } return groups; } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/database/ModemDB.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/database/ModemDB.java index 6bc556f66c..39f5a383d2 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/database/ModemDB.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/database/ModemDB.java @@ -14,6 +14,7 @@ package org.openhab.binding.insteon.internal.device.database; import java.io.ByteArrayOutputStream; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -38,12 +39,19 @@ import org.slf4j.LoggerFactory; */ @NonNullByDefault public class ModemDB { + /** + * List of known default controller groups with 0 being the standard one, + * while older third party software have used 254 or 255 + */ + private static final List DEFAULT_CONTROLLER_GROUPS = List.of(0, 254, 255); + private final Logger logger = LoggerFactory.getLogger(ModemDB.class); - private InsteonModem modem; - private Map dbes = new HashMap<>(); - private List records = new ArrayList<>(); - private List changes = new ArrayList<>(); + private final InsteonModem modem; + private final Map dbes = new HashMap<>(); + private final List records = new ArrayList<>(); + private final List changes = new ArrayList<>(); + private volatile int defaultControllerGroup = 0; private volatile boolean complete = false; public ModemDB(InsteonModem modem) { @@ -54,6 +62,10 @@ public class ModemDB { return modem.getDBM(); } + public int getDefaultControllerGroup() { + return defaultControllerGroup; + } + public List getDevices() { synchronized (dbes) { return dbes.keySet().stream().toList(); @@ -550,6 +562,17 @@ public class ModemDB { public void recordsLoaded() { logEntries(); setIsComplete(true); + setDefaultControllerGroup(); + } + + /** + * Sets the default controller group + */ + private void setDefaultControllerGroup() { + // Set the default controller group to the one with the most related devices + defaultControllerGroup = DEFAULT_CONTROLLER_GROUPS.stream() + .max(Comparator.comparingInt(group -> getRelatedDevices(group).size())).orElse(0); + logger.debug("set default controller group to {}", defaultControllerGroup); } /** @@ -583,9 +606,9 @@ public class ModemDB { } /** - * Returns a list of related devices for a given broadcast group + * Returns a list of related devices for a given group * - * @param group the broadcast group + * @param group the group * @return list of related device addresses */ public List getRelatedDevices(int group) { @@ -600,7 +623,7 @@ public class ModemDB { */ public List getBroadcastGroups() { return getEntries().stream().map(ModemDBEntry::getControllerGroups).flatMap(List::stream).distinct() - .filter(InsteonScene::isValidGroup).toList(); + .filter(this::isValidBroadcastGroup).toList(); } /** @@ -613,11 +636,21 @@ public class ModemDB { return getBroadcastGroups().contains(group); } + /** + * Returns if a broadcast group is valid + * + * @param group the broadcast group + * @return true if the broadcast group number is valid and not the default controller group + */ + public boolean isValidBroadcastGroup(int group) { + return InsteonScene.isValidGroup(group) && group != defaultControllerGroup; + } + /** * Returns the next available broadcast group */ public int getNextAvailableBroadcastGroup() { return IntStream.range(InsteonScene.GROUP_NEW_MIN, InsteonScene.GROUP_NEW_MAX) - .filter(group -> !hasBroadcastGroup(group)).min().orElse(-1); + .filter(group -> isValidBroadcastGroup(group) && !hasBroadcastGroup(group)).min().orElse(-1); } } diff --git a/bundles/org.openhab.binding.insteon/src/main/resources/OH-INF/thing/scene.xml b/bundles/org.openhab.binding.insteon/src/main/resources/OH-INF/thing/scene.xml index 642f5a0a3b..b5187eefb9 100644 --- a/bundles/org.openhab.binding.insteon/src/main/resources/OH-INF/thing/scene.xml +++ b/bundles/org.openhab.binding.insteon/src/main/resources/OH-INF/thing/scene.xml @@ -23,7 +23,7 @@ group - + Insteon scene group number.