[remoteopenhab] Listen to the new ChannelDescriptionChangedEvent events to update dynamic state/command options (#10885)

Also handle dynamic command options

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
This commit is contained in:
lolodomo 2021-06-22 21:19:45 +02:00 committed by GitHub
parent 58c7928b23
commit 34e26f806d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 275 additions and 16 deletions

View File

@ -0,0 +1,42 @@
/**
* Copyright (c) 2010-2021 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.remoteopenhab.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.thing.binding.BaseDynamicCommandDescriptionProvider;
import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
import org.openhab.core.thing.link.ItemChannelLinkRegistry;
import org.openhab.core.thing.type.DynamicCommandDescriptionProvider;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* Dynamic provider of command options
*
* @author Laurent Garnier - Initial contribution
*/
@Component(service = { DynamicCommandDescriptionProvider.class, RemoteopenhabCommandDescriptionOptionProvider.class })
@NonNullByDefault
public class RemoteopenhabCommandDescriptionOptionProvider extends BaseDynamicCommandDescriptionProvider {
@Activate
public RemoteopenhabCommandDescriptionOptionProvider(final @Reference EventPublisher eventPublisher, //
final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, //
final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
this.eventPublisher = eventPublisher;
this.itemChannelLinkRegistry = itemChannelLinkRegistry;
this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService;
}
}

View File

@ -75,6 +75,7 @@ public class RemoteopenhabHandlerFactory extends BaseThingHandlerFactory {
private final SseEventSourceFactory eventSourceFactory; private final SseEventSourceFactory eventSourceFactory;
private final RemoteopenhabChannelTypeProvider channelTypeProvider; private final RemoteopenhabChannelTypeProvider channelTypeProvider;
private final RemoteopenhabStateDescriptionOptionProvider stateDescriptionProvider; private final RemoteopenhabStateDescriptionOptionProvider stateDescriptionProvider;
private final RemoteopenhabCommandDescriptionOptionProvider commandDescriptionProvider;
private final Gson jsonParser; private final Gson jsonParser;
private HttpClient httpClientTrustingCert; private HttpClient httpClientTrustingCert;
@ -83,13 +84,15 @@ public class RemoteopenhabHandlerFactory extends BaseThingHandlerFactory {
public RemoteopenhabHandlerFactory(final @Reference HttpClientFactory httpClientFactory, public RemoteopenhabHandlerFactory(final @Reference HttpClientFactory httpClientFactory,
final @Reference ClientBuilder clientBuilder, final @Reference SseEventSourceFactory eventSourceFactory, final @Reference ClientBuilder clientBuilder, final @Reference SseEventSourceFactory eventSourceFactory,
final @Reference RemoteopenhabChannelTypeProvider channelTypeProvider, final @Reference RemoteopenhabChannelTypeProvider channelTypeProvider,
final @Reference RemoteopenhabStateDescriptionOptionProvider stateDescriptionProvider) { final @Reference RemoteopenhabStateDescriptionOptionProvider stateDescriptionProvider,
final @Reference RemoteopenhabCommandDescriptionOptionProvider commandDescriptionProvider) {
this.httpClient = httpClientFactory.getCommonHttpClient(); this.httpClient = httpClientFactory.getCommonHttpClient();
this.httpClientTrustingCert = httpClientFactory.createHttpClient(RemoteopenhabBindingConstants.BINDING_ID); this.httpClientTrustingCert = httpClientFactory.createHttpClient(RemoteopenhabBindingConstants.BINDING_ID);
this.clientBuilder = clientBuilder; this.clientBuilder = clientBuilder;
this.eventSourceFactory = eventSourceFactory; this.eventSourceFactory = eventSourceFactory;
this.channelTypeProvider = channelTypeProvider; this.channelTypeProvider = channelTypeProvider;
this.stateDescriptionProvider = stateDescriptionProvider; this.stateDescriptionProvider = stateDescriptionProvider;
this.commandDescriptionProvider = commandDescriptionProvider;
this.jsonParser = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.IDENTITY).create(); this.jsonParser = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.IDENTITY).create();
try { try {
@ -196,7 +199,8 @@ public class RemoteopenhabHandlerFactory extends BaseThingHandlerFactory {
ThingTypeUID thingTypeUID = thing.getThingTypeUID(); ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(RemoteopenhabBindingConstants.BRIDGE_TYPE_SERVER)) { if (thingTypeUID.equals(RemoteopenhabBindingConstants.BRIDGE_TYPE_SERVER)) {
return new RemoteopenhabBridgeHandler((Bridge) thing, httpClient, httpClientTrustingCert, clientBuilder, return new RemoteopenhabBridgeHandler((Bridge) thing, httpClient, httpClientTrustingCert, clientBuilder,
eventSourceFactory, channelTypeProvider, stateDescriptionProvider, jsonParser); eventSourceFactory, channelTypeProvider, stateDescriptionProvider, commandDescriptionProvider,
jsonParser);
} else if (RemoteopenhabBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { } else if (RemoteopenhabBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
return new RemoteopenhabThingHandler(thing); return new RemoteopenhabThingHandler(thing);
} }

View File

@ -0,0 +1,33 @@
/**
* Copyright (c) 2010-2021 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.remoteopenhab.internal.data;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* Payload from ChannelDescriptionChangedEvent events received through the SSE connection.
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class RemoteopenhabChannelDescriptionChangedEvent {
public String field = "";
public String channelUID = "";
public Set<String> linkedItemNames = Set.of();
public String value = "";
public @Nullable String oldValue = "";
}

View File

@ -0,0 +1,29 @@
/**
* Copyright (c) 2010-2021 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.remoteopenhab.internal.data;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* Part of {@link RemoteopenhabItem} containing the command description
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class RemoteopenhabCommandDescription {
public @Nullable List<RemoteopenhabCommandOption> commandOptions;
}

View File

@ -0,0 +1,27 @@
/**
* Copyright (c) 2010-2021 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.remoteopenhab.internal.data;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Part of {@link RemoteopenhabCommandDescription} containing one command option
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class RemoteopenhabCommandOption {
public String command = "";
public String label = "";
}

View File

@ -0,0 +1,29 @@
/**
* Copyright (c) 2010-2021 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.remoteopenhab.internal.data;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Match content of field value from {@link RemoteopenhabChannelDescriptionChangedEvent) event payload when event is for
* COMMAND_OPTIONS
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class RemoteopenhabCommandOptions {
public List<RemoteopenhabCommandOption> options = List.of();
}

View File

@ -29,4 +29,5 @@ public class RemoteopenhabItem {
public String state = ""; public String state = "";
public String groupType = ""; public String groupType = "";
public @Nullable RemoteopenhabStateDescription stateDescription; public @Nullable RemoteopenhabStateDescription stateDescription;
public @Nullable RemoteopenhabCommandDescription commandDescription;
} }

View File

@ -0,0 +1,29 @@
/**
* Copyright (c) 2010-2021 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.remoteopenhab.internal.data;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Match content of field value from {@link RemoteopenhabChannelDescriptionChangedEvent) event payload when event is for
* STATE_OPTIONS
*
* @author Laurent Garnier - Initial contribution
*/
@NonNullByDefault
public class RemoteopenhabStateOptions {
public List<RemoteopenhabStateOption> options = List.of();
}

View File

@ -32,8 +32,11 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.remoteopenhab.internal.RemoteopenhabChannelTypeProvider; import org.openhab.binding.remoteopenhab.internal.RemoteopenhabChannelTypeProvider;
import org.openhab.binding.remoteopenhab.internal.RemoteopenhabCommandDescriptionOptionProvider;
import org.openhab.binding.remoteopenhab.internal.RemoteopenhabStateDescriptionOptionProvider; import org.openhab.binding.remoteopenhab.internal.RemoteopenhabStateDescriptionOptionProvider;
import org.openhab.binding.remoteopenhab.internal.config.RemoteopenhabServerConfiguration; import org.openhab.binding.remoteopenhab.internal.config.RemoteopenhabServerConfiguration;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabCommandDescription;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabCommandOption;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabItem; import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabItem;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabStateDescription; import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabStateDescription;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabStateOption; import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabStateOption;
@ -69,6 +72,7 @@ import org.openhab.core.thing.type.ChannelType;
import org.openhab.core.thing.type.ChannelTypeBuilder; import org.openhab.core.thing.type.ChannelTypeBuilder;
import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.Command; import org.openhab.core.types.Command;
import org.openhab.core.types.CommandOption;
import org.openhab.core.types.RefreshType; import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State; import org.openhab.core.types.State;
import org.openhab.core.types.StateDescriptionFragmentBuilder; import org.openhab.core.types.StateDescriptionFragmentBuilder;
@ -101,6 +105,7 @@ public class RemoteopenhabBridgeHandler extends BaseBridgeHandler
private final HttpClient httpClientTrustingCert; private final HttpClient httpClientTrustingCert;
private final RemoteopenhabChannelTypeProvider channelTypeProvider; private final RemoteopenhabChannelTypeProvider channelTypeProvider;
private final RemoteopenhabStateDescriptionOptionProvider stateDescriptionProvider; private final RemoteopenhabStateDescriptionOptionProvider stateDescriptionProvider;
private final RemoteopenhabCommandDescriptionOptionProvider commandDescriptionProvider;
private final Object updateThingLock = new Object(); private final Object updateThingLock = new Object();
@ -114,11 +119,13 @@ public class RemoteopenhabBridgeHandler extends BaseBridgeHandler
public RemoteopenhabBridgeHandler(Bridge bridge, HttpClient httpClient, HttpClient httpClientTrustingCert, public RemoteopenhabBridgeHandler(Bridge bridge, HttpClient httpClient, HttpClient httpClientTrustingCert,
ClientBuilder clientBuilder, SseEventSourceFactory eventSourceFactory, ClientBuilder clientBuilder, SseEventSourceFactory eventSourceFactory,
RemoteopenhabChannelTypeProvider channelTypeProvider, RemoteopenhabChannelTypeProvider channelTypeProvider,
RemoteopenhabStateDescriptionOptionProvider stateDescriptionProvider, final Gson jsonParser) { RemoteopenhabStateDescriptionOptionProvider stateDescriptionProvider,
RemoteopenhabCommandDescriptionOptionProvider commandDescriptionProvider, final Gson jsonParser) {
super(bridge); super(bridge);
this.httpClientTrustingCert = httpClientTrustingCert; this.httpClientTrustingCert = httpClientTrustingCert;
this.channelTypeProvider = channelTypeProvider; this.channelTypeProvider = channelTypeProvider;
this.stateDescriptionProvider = stateDescriptionProvider; this.stateDescriptionProvider = stateDescriptionProvider;
this.commandDescriptionProvider = commandDescriptionProvider;
this.restClient = new RemoteopenhabRestClient(httpClient, clientBuilder, eventSourceFactory, jsonParser); this.restClient = new RemoteopenhabRestClient(httpClient, clientBuilder, eventSourceFactory, jsonParser);
} }
@ -314,18 +321,31 @@ public class RemoteopenhabBridgeHandler extends BaseBridgeHandler
} }
} }
private void setStateOptions(List<RemoteopenhabItem> items) { private void setDynamicOptions(List<RemoteopenhabItem> items) {
for (RemoteopenhabItem item : items) { for (RemoteopenhabItem item : items) {
Channel channel = getThing().getChannel(item.name); Channel channel = getThing().getChannel(item.name);
RemoteopenhabStateDescription descr = item.stateDescription; if (channel == null) {
List<RemoteopenhabStateOption> options = descr == null ? null : descr.options; continue;
if (channel != null && options != null && !options.isEmpty()) {
List<StateOption> stateOptions = new ArrayList<>();
for (RemoteopenhabStateOption option : options) {
stateOptions.add(new StateOption(option.value, option.label));
} }
stateDescriptionProvider.setStateOptions(channel.getUID(), stateOptions); RemoteopenhabStateDescription stateDescr = item.stateDescription;
logger.trace("{} options set for the channel {}", options.size(), channel.getUID()); List<RemoteopenhabStateOption> stateOptions = stateDescr == null ? null : stateDescr.options;
if (stateOptions != null && !stateOptions.isEmpty()) {
List<StateOption> options = new ArrayList<>();
for (RemoteopenhabStateOption option : stateOptions) {
options.add(new StateOption(option.value, option.label));
}
stateDescriptionProvider.setStateOptions(channel.getUID(), options);
logger.trace("{} state options set for the channel {}", options.size(), channel.getUID());
}
RemoteopenhabCommandDescription commandDescr = item.commandDescription;
List<RemoteopenhabCommandOption> commandOptions = commandDescr == null ? null : commandDescr.commandOptions;
if (commandOptions != null && !commandOptions.isEmpty()) {
List<CommandOption> options = new ArrayList<>();
for (RemoteopenhabCommandOption option : commandOptions) {
options.add(new CommandOption(option.command, option.label));
}
commandDescriptionProvider.setCommandOptions(channel.getUID(), options);
logger.trace("{} command options set for the channel {}", options.size(), channel.getUID());
} }
} }
} }
@ -341,7 +361,7 @@ public class RemoteopenhabBridgeHandler extends BaseBridgeHandler
List<RemoteopenhabItem> items = restClient.getRemoteItems("name,type,groupType,state,stateDescription"); List<RemoteopenhabItem> items = restClient.getRemoteItems("name,type,groupType,state,stateDescription");
if (createChannels(items, true)) { if (createChannels(items, true)) {
setStateOptions(items); setDynamicOptions(items);
for (RemoteopenhabItem item : items) { for (RemoteopenhabItem item : items) {
updateChannelState(item.name, null, item.state, false); updateChannelState(item.name, null, item.state, false);
} }
@ -467,6 +487,11 @@ public class RemoteopenhabBridgeHandler extends BaseBridgeHandler
} }
} }
@Override
public void onItemOptionsUpdatedd(RemoteopenhabItem item) {
setDynamicOptions(List.of(item));
}
private void updateChannelState(String itemName, @Nullable String stateType, String state, private void updateChannelState(String itemName, @Nullable String stateType, String state,
boolean onlyIfStateChanged) { boolean onlyIfStateChanged) {
Channel channel = getThing().getChannel(itemName); Channel channel = getThing().getChannel(itemName);

View File

@ -43,4 +43,9 @@ public interface RemoteopenhabItemsDataListener {
* A new ItemUpdatedEvent was published. * A new ItemUpdatedEvent was published.
*/ */
void onItemUpdated(RemoteopenhabItem newItem, RemoteopenhabItem oldItem); void onItemUpdated(RemoteopenhabItem newItem, RemoteopenhabItem oldItem);
/**
* A new ChannelDescriptionChangedEvent with updated state options or updated command options was published.
*/
void onItemOptionsUpdatedd(RemoteopenhabItem item);
} }

View File

@ -46,11 +46,16 @@ import org.eclipse.jetty.client.util.InputStreamResponseListener;
import org.eclipse.jetty.client.util.StringContentProvider; import org.eclipse.jetty.client.util.StringContentProvider;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabChannelDescriptionChangedEvent;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabChannelTriggerEvent; import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabChannelTriggerEvent;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabCommandDescription;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabCommandOptions;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabEvent; import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabEvent;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabEventPayload; import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabEventPayload;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabItem; import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabItem;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabRestApi; import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabRestApi;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabStateDescription;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabStateOptions;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabStatusInfo; import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabStatusInfo;
import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabThing; import org.openhab.binding.remoteopenhab.internal.data.RemoteopenhabThing;
import org.openhab.binding.remoteopenhab.internal.exceptions.RemoteopenhabException; import org.openhab.binding.remoteopenhab.internal.exceptions.RemoteopenhabException;
@ -321,8 +326,9 @@ public class RemoteopenhabRestClient {
String url; String url;
try { try {
url = String.format("%s?topics=%s/items/*/*,%s/things/*/*,%s/channels/*/triggered", getRestApiUrl("events"), url = String.format(
getTopicNamespace(), getTopicNamespace(), getTopicNamespace()); "%s?topics=%s/items/*/*,%s/things/*/*,%s/channels/*/triggered,openhab/channels/*/descriptionchanged",
getRestApiUrl("events"), getTopicNamespace(), getTopicNamespace(), getTopicNamespace());
} catch (RemoteopenhabException e) { } catch (RemoteopenhabException e) {
logger.debug("{}", e.getMessage()); logger.debug("{}", e.getMessage());
return; return;
@ -383,7 +389,7 @@ public class RemoteopenhabRestClient {
private void onEvent(InboundSseEvent inboundEvent) { private void onEvent(InboundSseEvent inboundEvent) {
String name = inboundEvent.getName(); String name = inboundEvent.getName();
String data = inboundEvent.readData(); String data = inboundEvent.readData();
logger.trace("Received event name {} date {}", name, data); logger.trace("Received event name {} data {}", name, data);
lastEventTimestamp = System.currentTimeMillis(); lastEventTimestamp = System.currentTimeMillis();
if (!connected) { if (!connected) {
@ -468,6 +474,35 @@ public class RemoteopenhabRestClient {
thingsListeners thingsListeners
.forEach(listener -> listener.onChannelTriggered(triggerEvent.channel, triggerEvent.event)); .forEach(listener -> listener.onChannelTriggered(triggerEvent.channel, triggerEvent.event));
break; break;
case "ChannelDescriptionChangedEvent":
RemoteopenhabStateDescription stateDescription = new RemoteopenhabStateDescription();
RemoteopenhabCommandDescription commandDescription = new RemoteopenhabCommandDescription();
RemoteopenhabChannelDescriptionChangedEvent descriptionChanged = Objects.requireNonNull(
jsonParser.fromJson(event.payload, RemoteopenhabChannelDescriptionChangedEvent.class));
switch (descriptionChanged.field) {
case "STATE_OPTIONS":
RemoteopenhabStateOptions stateOptions = Objects.requireNonNull(
jsonParser.fromJson(descriptionChanged.value, RemoteopenhabStateOptions.class));
stateDescription.options = stateOptions.options;
break;
case "COMMAND_OPTIONS":
RemoteopenhabCommandOptions commandOptions = Objects.requireNonNull(
jsonParser.fromJson(descriptionChanged.value, RemoteopenhabCommandOptions.class));
commandDescription.commandOptions = commandOptions.options;
break;
default:
break;
}
if (stateDescription.options != null || commandDescription.commandOptions != null) {
descriptionChanged.linkedItemNames.forEach(linkedItemName -> {
RemoteopenhabItem item1 = new RemoteopenhabItem();
item1.name = linkedItemName;
item1.stateDescription = stateDescription;
item1.commandDescription = commandDescription;
itemsListeners.forEach(listener -> listener.onItemOptionsUpdatedd(item1));
});
}
break;
case "ItemStatePredictedEvent": case "ItemStatePredictedEvent":
case "ItemCommandEvent": case "ItemCommandEvent":
case "ThingStatusInfoEvent": case "ThingStatusInfoEvent":