diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/ChannelStateDescriptionProvider.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/ChannelStateDescriptionProvider.java index d2a7abe51e3..2f4bb689ffe 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/ChannelStateDescriptionProvider.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/ChannelStateDescriptionProvider.java @@ -21,7 +21,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.items.Item; -import org.openhab.core.library.CoreItemFactory; import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ThingRegistry; @@ -100,22 +99,6 @@ public Integer getRank() { ChannelType channelType = thingTypeRegistry.getChannelType(channel, locale); if (channelType != null) { stateDescription = channelType.getState(); - String itemType = channelType.getItemType(); - if (itemType != null && (stateDescription == null || stateDescription.getPattern() == null)) { - String pattern = null; - if (CoreItemFactory.STRING.equalsIgnoreCase(itemType)) { - pattern = "%s"; - } else if (itemType.startsWith(CoreItemFactory.NUMBER)) { - pattern = "%.0f"; - } - if (pattern != null) { - logger.trace("Provide a default pattern {} for item {}", pattern, itemName); - StateDescriptionFragmentBuilder builder = (stateDescription == null) - ? StateDescriptionFragmentBuilder.create() - : StateDescriptionFragmentBuilder.create(stateDescription); - stateDescription = builder.withPattern(pattern).build().toStateDescription(); - } - } } StateDescription dynamicStateDescription = getDynamicStateDescription(channel, stateDescription, locale); diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/items/DefaultStateDescriptionFragmentProvider.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/items/DefaultStateDescriptionFragmentProvider.java new file mode 100644 index 00000000000..506b5fe77e7 --- /dev/null +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/items/DefaultStateDescriptionFragmentProvider.java @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2010-2024 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.core.internal.items; + +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.library.CoreItemFactory; +import org.openhab.core.types.StateDescriptionFragment; +import org.openhab.core.types.StateDescriptionFragmentBuilder; +import org.openhab.core.types.StateDescriptionFragmentProvider; +import org.osgi.framework.Constants; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A {@link StateDescriptionFragment} provider providing a default state pattern for items of type String, + * DateTime and Number (with or without dimension). + * + * @author Laurent Garnier - initial contribution + * + */ +@NonNullByDefault +@Component(service = { StateDescriptionFragmentProvider.class, + DefaultStateDescriptionFragmentProvider.class }, immediate = true, property = { "service.ranking:Integer=-2" }) +public class DefaultStateDescriptionFragmentProvider implements StateDescriptionFragmentProvider { + + private static final StateDescriptionFragment DEFAULT_STRING = StateDescriptionFragmentBuilder.create() + .withPattern("%s").build(); + private static final StateDescriptionFragment DEFAULT_DATETIME = StateDescriptionFragmentBuilder.create() + .withPattern("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS").build(); + private static final StateDescriptionFragment DEFAULT_NUMBER = StateDescriptionFragmentBuilder.create() + .withPattern("%.0f").build(); + private static final StateDescriptionFragment DEFAULT_NUMBER_WITH_DIMENSION = StateDescriptionFragmentBuilder + .create().withPattern("%.0f %unit%").build(); + + private final Logger logger = LoggerFactory.getLogger(DefaultStateDescriptionFragmentProvider.class); + + private final Map stateDescriptionFragments = new ConcurrentHashMap<>(); + + private Integer rank = -2; // takes less precedence over all other providers + + @Activate + public DefaultStateDescriptionFragmentProvider(Map properties) { + Object serviceRanking = properties.get(Constants.SERVICE_RANKING); + if (serviceRanking instanceof Integer) { + rank = (Integer) serviceRanking; + } + } + + @Deactivate + protected void deactivate() { + removeAllItems(); + } + + public void addItem(String itemName, String itemType) { + logger.debug("DefaultStateDescriptionFragmentProvider addItem {} {}", itemName, itemType); + if (itemType.startsWith(CoreItemFactory.NUMBER + ":")) { + stateDescriptionFragments.put(itemName, DEFAULT_NUMBER_WITH_DIMENSION); + } else { + switch (itemType) { + case CoreItemFactory.STRING: + stateDescriptionFragments.put(itemName, DEFAULT_STRING); + break; + case CoreItemFactory.DATETIME: + stateDescriptionFragments.put(itemName, DEFAULT_DATETIME); + break; + case CoreItemFactory.NUMBER: + stateDescriptionFragments.put(itemName, DEFAULT_NUMBER); + break; + default: + stateDescriptionFragments.remove(itemName); + } + } + } + + public void removeItem(String itemName) { + logger.debug("DefaultStateDescriptionFragmentProvider removeItem {}", itemName); + stateDescriptionFragments.remove(itemName); + } + + public void removeAllItems() { + logger.debug("DefaultStateDescriptionFragmentProvider removeAllItems"); + stateDescriptionFragments.clear(); + } + + @Override + public @Nullable StateDescriptionFragment getStateDescriptionFragment(String itemName, @Nullable Locale locale) { + return stateDescriptionFragments.get(itemName); + } + + @Override + public Integer getRank() { + return rank; + } +} diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/items/ItemRegistryImpl.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/items/ItemRegistryImpl.java index c61b163083d..1b84001861c 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/items/ItemRegistryImpl.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/items/ItemRegistryImpl.java @@ -71,6 +71,7 @@ public class ItemRegistryImpl extends AbstractRegistry options = List.of(new StateOption("value", "label"));