[insteon] Improve modem db default controller group support (#18465)

Signed-off-by: Jeremy Setton <jeremy.setton@gmail.com>
This commit is contained in:
Jeremy
2025-03-30 10:29:43 +02:00
committed by GitHub
parent 1ae51c7a97
commit d27146d6af
6 changed files with 52 additions and 21 deletions
@@ -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`
@@ -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);
@@ -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);
}
@@ -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<Integer, LinkDBRecord> records = new TreeMap<>(Collections.reverseOrder());
private TreeMap<Integer, LinkDBChange> changes = new TreeMap<>(Collections.reverseOrder());
private final InsteonDevice device;
private final TreeMap<Integer, LinkDBRecord> records = new TreeMap<>(Collections.reverseOrder());
private final TreeMap<Integer, LinkDBChange> 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;
}
@@ -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<Integer> DEFAULT_CONTROLLER_GROUPS = List.of(0, 254, 255);
private final Logger logger = LoggerFactory.getLogger(ModemDB.class);
private InsteonModem modem;
private Map<InsteonAddress, ModemDBEntry> dbes = new HashMap<>();
private List<ModemDBRecord> records = new ArrayList<>();
private List<ModemDBChange> changes = new ArrayList<>();
private final InsteonModem modem;
private final Map<InsteonAddress, ModemDBEntry> dbes = new HashMap<>();
private final List<ModemDBRecord> records = new ArrayList<>();
private final List<ModemDBChange> 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<InsteonAddress> 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<InsteonAddress> getRelatedDevices(int group) {
@@ -600,7 +623,7 @@ public class ModemDB {
*/
public List<Integer> 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);
}
}
@@ -23,7 +23,7 @@
<representation-property>group</representation-property>
<config-description>
<parameter name="group" type="integer" min="2" max="254" required="true">
<parameter name="group" type="integer" min="0" max="255" required="true">
<label>Group</label>
<description>Insteon scene group number.</description>
</parameter>