Skip to content

Commit c7e7f30

Browse files
authored
[insteon] Fix legacy backward compatibility (openhab#17981)
Signed-off-by: jsetton <[email protected]>
1 parent d049995 commit c7e7f30

File tree

5 files changed

+52
-51
lines changed

5 files changed

+52
-51
lines changed

bundles/org.openhab.binding.insteon/README.md

+19-18
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ You can follow the [migration guide](#migration-guide).
2626

2727
However, the new version is fully backward compatible by supporting the legacy things.
2828
On the first start, existing `device` things connected to a `network` bridge will be migrated to the `legacy-device` thing type while still keeping the same ids to prevent any breakage.
29+
For textual configuration with defined thing channels, the channel types must be manually updated to the new ones by adding the `legacy` prefix and capitalizing the first letter, as shown in [these examples](#full-example).
2930
It is important to note that once the migration has occurred, downgrading to an older version will not be possible.
3031

3132
## Supported Things
@@ -474,27 +475,27 @@ Bridge insteon:plm:home [serialPort="/dev/ttyUSB0"] {
474475
Bridge insteon:network:home [port="/dev/ttyUSB0"] {
475476
Thing device 22F8A8 [address="22.F8.A8", productKey="F00.00.15"] {
476477
Channels:
477-
Type keypadButtonA : keypadButtonA [ group=3 ]
478-
Type keypadButtonB : keypadButtonB [ group=4 ]
479-
Type keypadButtonC : keypadButtonC [ group=5 ]
480-
Type keypadButtonD : keypadButtonD [ group=6 ]
478+
Type legacyKeypadButtonA : keypadButtonA [ group=3 ]
479+
Type legacyKeypadButtonB : keypadButtonB [ group=4 ]
480+
Type legacyKeypadButtonC : keypadButtonC [ group=5 ]
481+
Type legacyKeypadButtonD : keypadButtonD [ group=6 ]
481482
}
482483
Thing device 238D93 [address="23.8D.93", productKey="F00.00.12"]
483484
Thing device 238F55 [address="23.8F.55", productKey="F00.00.11"] {
484485
Channels:
485-
Type dimmer : dimmer [related="23.B0.D9+23.8F.C9"]
486+
Type legacyDimmer : dimmer [related="23.B0.D9+23.8F.C9"]
486487
}
487488
Thing device 238FC9 [address="23.8F.C9", productKey="F00.00.11"] {
488489
Channels:
489-
Type dimmer : dimmer [related="23.8F.55+23.B0.D9"]
490+
Type legacyDimmer : dimmer [related="23.8F.55+23.B0.D9"]
490491
}
491492
Thing device 23B0D9 [address="23.B0.D9", productKey="F00.00.11"] {
492493
Channels:
493-
Type dimmer : dimmer [related="23.8F.55+23.8F.C9"]
494+
Type legacyDimmer : dimmer [related="23.8F.55+23.8F.C9"]
494495
}
495496
Thing device 243141 [address="24.31.41", productKey="F00.00.11"] {
496497
Channels:
497-
Type dimmer : dimmer [dimmermax=60]
498+
Type legacyDimmer : dimmer [dimmermax=60]
498499
}
499500
}
500501
```
@@ -644,11 +645,11 @@ Thing device 23b0d9 [address="23.B0.D9"] {
644645
Bridge insteon:network:home [port="/dev/ttyUSB0"] {
645646
Thing device AABBCC [address="AA.BB.CC", productKey="F00.00.11"] {
646647
Channels:
647-
Type dimmer : dimmer [dimmermax=70]
648+
Type legacyDimmer : dimmer [dimmermax=70]
648649
}
649650
Thing device AABBCD [address="AA.BB.CD", productKey="F00.00.15"] {
650651
Channels:
651-
Type loadDimmer : loadDimmer [dimmermax=60]
652+
Type legacyLoadDimmer : loadDimmer [dimmermax=60]
652653
}
653654
}
654655
```
@@ -782,10 +783,10 @@ end
782783
Bridge insteon:network:home [port="/dev/ttyUSB0"] {
783784
Thing device AABBCC [address="AA.BB.CC", productKey="F00.00.15"] {
784785
Channels:
785-
Type keypadButtonA : keypadButtonA [ group="0xf3" ]
786-
Type keypadButtonB : keypadButtonB [ group="0xf4" ]
787-
Type keypadButtonC : keypadButtonC [ group="0xf5" ]
788-
Type keypadButtonD : keypadButtonD [ group="0xf6" ]
786+
Type legacyKeypadButtonA : keypadButtonA [ group="0xf3" ]
787+
Type legacyKeypadButtonB : keypadButtonB [ group="0xf4" ]
788+
Type legacyKeypadButtonC : keypadButtonC [ group="0xf5" ]
789+
Type legacyKeypadButtonD : keypadButtonD [ group="0xf6" ]
789790
}
790791
}
791792
```
@@ -1324,7 +1325,7 @@ An `ON` state indicates that all the device states associated to a scene are mat
13241325
Bridge insteon:network:home [port="/dev/ttyUSB0"] {
13251326
Thing device AABBCC [address="AA.BB.CC", productKey="0x000045"] {
13261327
Channels:
1327-
Type broadcastOnOff : broadcastOnOff#2
1328+
Type legacyBroadcastOnOff : broadcastOnOff#2
13281329
}
13291330
}
13301331
```
@@ -1426,11 +1427,11 @@ For scenes, these will be polled based on the modem database, after sending a gr
14261427
Bridge insteon:network:home [port="/dev/ttyUSB0"] {
14271428
Thing device AABBCC [address="AA.BB.CC", productKey="F00.00.11"] {
14281429
Channels:
1429-
Type dimmer : dimmer [related="AA.BB.DD"]
1430+
Type legacyDimmer : dimmer [related="AA.BB.DD"]
14301431
}
14311432
Thing device AABBDD [address="AA.BB.DD", productKey="F00.00.11"] {
14321433
Channels:
1433-
Type dimmer : dimmer [related="AA.BB.CC"]
1434+
Type legacyDimmer : dimmer [related="AA.BB.CC"]
14341435
}
14351436
}
14361437
```
@@ -1444,7 +1445,7 @@ For scenes, these will be polled based on the modem database, after sending a gr
14441445
Bridge insteon:network:home [port="/dev/ttyUSB0"] {
14451446
Thing device AABBCC [address="AA.BB.CC", productKey="0x000045"] {
14461447
Channels:
1447-
Type broadcastOnOff : broadcastOnOff#3 [related="AA.BB.DD+AA.BB.EE"]
1448+
Type legacyBroadcastOnOff : broadcastOnOff#3 [related="AA.BB.DD+AA.BB.EE"]
14481449
}
14491450
Thing device AABBDD [address="AA.BB.DD", productKey="F00.00.11"]
14501451
Thing device AABBEE [address="AA.BB.EE", productKey="F00.00.11"]

bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/discovery/InsteonLegacyDiscoveryService.java

+3
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,16 @@ public void addInsteonDevices(List<InsteonAddress> addresses) {
5959
ThingUID bridgeUID = handler.getThing().getUID();
6060
String id = address.toString().replace(".", "");
6161
ThingUID thingUID = new ThingUID(THING_TYPE_LEGACY_DEVICE, bridgeUID, id);
62+
ThingUID oldThingUID = new ThingUID(THING_TYPE_DEVICE, bridgeUID, id);
6263
String label = "Insteon Device (Legacy) " + address;
6364
Map<String, Object> properties = new HashMap<>();
6465
properties.put(PROPERTY_DEVICE_ADDRESS, address.toString());
6566

6667
thingDiscovered(DiscoveryResultBuilder.create(thingUID).withBridge(bridgeUID).withLabel(label)
6768
.withProperties(properties).withRepresentationProperty(PROPERTY_DEVICE_ADDRESS).build());
6869

70+
thingRemoved(oldThingUID);
71+
6972
logger.debug("added Insteon device {} to inbox", address);
7073
}
7174
}

bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonDeviceHandler.java

+1-7
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,8 @@
1515
import static org.openhab.binding.insteon.internal.InsteonBindingConstants.*;
1616

1717
import java.util.List;
18-
import java.util.Map;
1918
import java.util.concurrent.ScheduledFuture;
2019
import java.util.concurrent.TimeUnit;
21-
import java.util.stream.Collectors;
2220

2321
import org.eclipse.jdt.annotation.NonNullByDefault;
2422
import org.eclipse.jdt.annotation.Nullable;
@@ -32,7 +30,6 @@
3230
import org.openhab.binding.insteon.internal.device.InsteonDevice;
3331
import org.openhab.binding.insteon.internal.device.InsteonEngine;
3432
import org.openhab.binding.insteon.internal.device.InsteonModem;
35-
import org.openhab.core.config.core.Configuration;
3633
import org.openhab.core.thing.Bridge;
3734
import org.openhab.core.thing.Channel;
3835
import org.openhab.core.thing.ChannelUID;
@@ -114,10 +111,7 @@ public void initialize() {
114111

115112
private void changeThingType(ThingTypeUID thingTypeUID, @Nullable BridgeHandler bridgeHandler) {
116113
if (bridgeHandler instanceof InsteonLegacyNetworkHandler legacyNetworkHandler) {
117-
Map<ChannelUID, Configuration> channelConfigs = getThing().getChannels().stream()
118-
.collect(Collectors.toMap(Channel::getUID, Channel::getConfiguration));
119-
120-
legacyNetworkHandler.addChannelConfigs(channelConfigs);
114+
getThing().getChannels().forEach(legacyNetworkHandler::cacheChannel);
121115
}
122116

123117
changeThingType(thingTypeUID, getConfig());

bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonLegacyDeviceHandler.java

+18-20
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,9 @@
1919
import java.util.ArrayList;
2020
import java.util.Collections;
2121
import java.util.HashMap;
22-
import java.util.HashSet;
2322
import java.util.List;
2423
import java.util.Map;
2524
import java.util.Objects;
26-
import java.util.Set;
2725

2826
import org.eclipse.jdt.annotation.NonNullByDefault;
2927
import org.eclipse.jdt.annotation.Nullable;
@@ -37,7 +35,6 @@
3735
import org.openhab.binding.insteon.internal.device.LegacyDeviceFeature;
3836
import org.openhab.binding.insteon.internal.device.LegacyDeviceTypeLoader;
3937
import org.openhab.binding.insteon.internal.device.X10Address;
40-
import org.openhab.core.config.core.Configuration;
4138
import org.openhab.core.thing.Bridge;
4239
import org.openhab.core.thing.Channel;
4340
import org.openhab.core.thing.ChannelUID;
@@ -46,6 +43,7 @@
4643
import org.openhab.core.thing.ThingStatusDetail;
4744
import org.openhab.core.thing.binding.BaseThingHandler;
4845
import org.openhab.core.thing.binding.ThingHandlerCallback;
46+
import org.openhab.core.thing.binding.builder.ChannelBuilder;
4947
import org.openhab.core.thing.type.ChannelTypeUID;
5048
import org.openhab.core.types.Command;
5149
import org.openhab.core.util.StringUtils;
@@ -203,12 +201,17 @@ public void initialize() {
203201
if (feature != null) {
204202
if (!feature.isFeatureGroup()) {
205203
if (channelId.equalsIgnoreCase(BROADCAST_ON_OFF)) {
206-
Set<String> broadcastChannels = new HashSet<>();
207204
for (Channel channel : thing.getChannels()) {
208205
String id = channel.getUID().getId();
209206
if (id.startsWith(BROADCAST_ON_OFF)) {
210207
channelMap.put(id, channel);
211-
broadcastChannels.add(id);
208+
}
209+
}
210+
211+
for (Channel channel : getInsteonNetworkHandler().getCachedChannels(thing.getUID())) {
212+
String id = channel.getUID().getId();
213+
if (id.startsWith(BROADCAST_ON_OFF)) {
214+
channelMap.putIfAbsent(id, createChannel(id, BROADCAST_ON_OFF, callback));
212215
}
213216
}
214217

@@ -220,10 +223,7 @@ public void initialize() {
220223
for (Object value : list) {
221224
if (value instanceof Double doubleValue && doubleValue % 1 == 0) {
222225
String id = BROADCAST_ON_OFF + "#" + doubleValue.intValue();
223-
if (!broadcastChannels.contains(id)) {
224-
channelMap.put(id, createChannel(id, BROADCAST_ON_OFF, callback));
225-
broadcastChannels.add(id);
226-
}
226+
channelMap.putIfAbsent(id, createChannel(id, BROADCAST_ON_OFF, callback));
227227
} else {
228228
valid = false;
229229
break;
@@ -315,6 +315,9 @@ public void dispose() {
315315
if (getBridge() != null && address != null) {
316316
getInsteonBinding().removeDevice(address);
317317

318+
getThing().getChannels().stream().map(Channel::getUID).filter(this::isLinked)
319+
.forEach(this::channelUnlinked);
320+
318321
logger.debug("removed {} address = {}", getThing().getUID().getAsString(), address);
319322
}
320323

@@ -481,23 +484,18 @@ private Channel createChannel(String channelId, String channelTypeId, ThingHandl
481484
ChannelUID channelUID = new ChannelUID(getThing().getUID(), channelId);
482485
ChannelTypeUID channelTypeUID = new ChannelTypeUID(InsteonBindingConstants.BINDING_ID,
483486
CHANNEL_TYPE_ID_PREFIX + StringUtils.capitalize(channelTypeId));
484-
Configuration channelConfig = getChannelConfig(channelUID);
487+
Channel oldChannel = getInsteonNetworkHandler().pollCachedChannel(channelUID);
485488
Channel channel = getThing().getChannel(channelUID);
486489
if (channel == null) {
487-
channel = callback.createChannelBuilder(channelUID, channelTypeUID).withConfiguration(channelConfig)
488-
.build();
490+
if (oldChannel == null) {
491+
channel = callback.createChannelBuilder(channelUID, channelTypeUID).build();
492+
} else {
493+
channel = ChannelBuilder.create(oldChannel).withType(channelTypeUID).build();
494+
}
489495
}
490496
return channel;
491497
}
492498

493-
private Configuration getChannelConfig(ChannelUID channelUID) {
494-
try {
495-
return getInsteonNetworkHandler().getChannelConfig(channelUID);
496-
} catch (IllegalArgumentException e) {
497-
return new Configuration();
498-
}
499-
}
500-
501499
private InsteonLegacyNetworkHandler getInsteonNetworkHandler() {
502500
Bridge bridge = getBridge();
503501
if (bridge == null) {

bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonLegacyNetworkHandler.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@
2828
import org.openhab.binding.insteon.internal.device.DeviceAddress;
2929
import org.openhab.binding.insteon.internal.device.InsteonAddress;
3030
import org.openhab.binding.insteon.internal.discovery.InsteonLegacyDiscoveryService;
31-
import org.openhab.core.config.core.Configuration;
3231
import org.openhab.core.io.console.Console;
3332
import org.openhab.core.io.transport.serial.SerialPortManager;
3433
import org.openhab.core.thing.Bridge;
34+
import org.openhab.core.thing.Channel;
3535
import org.openhab.core.thing.ChannelUID;
3636
import org.openhab.core.thing.Thing;
3737
import org.openhab.core.thing.ThingManager;
@@ -74,7 +74,7 @@ public class InsteonLegacyNetworkHandler extends BaseBridgeHandler {
7474
private ThingRegistry thingRegistry;
7575
private Map<String, String> deviceInfo = new ConcurrentHashMap<>();
7676
private Map<String, String> channelInfo = new ConcurrentHashMap<>();
77-
private Map<ChannelUID, Configuration> channelConfigs = new ConcurrentHashMap<>();
77+
private Map<ChannelUID, Channel> channelCache = new ConcurrentHashMap<>();
7878

7979
public InsteonLegacyNetworkHandler(Bridge bridge, HttpClient httpClient, SerialPortManager serialPortManager,
8080
ThingManager thingManager, ThingRegistry thingRegistry) {
@@ -318,12 +318,17 @@ public void unlinked(ChannelUID uid) {
318318
channelInfo.remove(uid.getAsString());
319319
}
320320

321-
public Configuration getChannelConfig(ChannelUID channelUID) {
322-
return channelConfigs.getOrDefault(channelUID, new Configuration());
321+
public List<Channel> getCachedChannels(ThingUID thingUID) {
322+
return channelCache.values().stream().filter(channel -> channel.getUID().getThingUID().equals(thingUID))
323+
.toList();
323324
}
324325

325-
public void addChannelConfigs(Map<ChannelUID, Configuration> channelConfigs) {
326-
this.channelConfigs.putAll(channelConfigs);
326+
public @Nullable Channel pollCachedChannel(ChannelUID channelUID) {
327+
return channelCache.remove(channelUID);
328+
}
329+
330+
public void cacheChannel(Channel channel) {
331+
channelCache.put(channel.getUID(), channel);
327332
}
328333

329334
private void display(Console console, Map<String, String> info) {

0 commit comments

Comments
 (0)