From 99ec7dbda38669b2928d085887d91d85c9e74540 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Wed, 31 May 2023 17:39:52 +0200 Subject: [PATCH 1/7] expose widget format pattern to sitemap REST Signed-off-by: Mark Herwege --- .../sitemap/internal/PageChangeListener.java | 2 + .../sitemap/internal/SitemapResource.java | 2 + .../sitemap/internal/SitemapWidgetEvent.java | 2 + .../io/rest/sitemap/internal/WidgetDTO.java | 3 + .../ui/internal/items/ItemUIRegistryImpl.java | 93 ++++++++++++++----- .../openhab/core/ui/items/ItemUIRegistry.java | 10 ++ 6 files changed, 91 insertions(+), 21 deletions(-) diff --git a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/PageChangeListener.java b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/PageChangeListener.java index 3252af2f6bd..976e3f6467f 100644 --- a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/PageChangeListener.java +++ b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/PageChangeListener.java @@ -44,6 +44,7 @@ * * @author Kai Kreuzer - Initial contribution * @author Laurent Garnier - Added support for icon color + * @author Mark Herwege - Added format pattern field */ public class PageChangeListener implements StateChangeListener { @@ -238,6 +239,7 @@ private SitemapWidgetEvent constructSitemapEventForWidget(Item item, State state event.sitemapName = sitemapName; event.pageId = pageId; event.label = itemUIRegistry.getLabel(widget); + event.pattern = itemUIRegistry.getFormatPattern(widget); event.widgetId = itemUIRegistry.getWidgetId(widget); event.visibility = itemUIRegistry.getVisiblity(widget); event.descriptionChanged = false; diff --git a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java index 478f244a141..10f47b98a63 100644 --- a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java +++ b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java @@ -125,6 +125,7 @@ * @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification * @author Wouter Born - Migrated to OpenAPI annotations * @author Laurent Garnier - Added support for icon color + * @author Mark Herwege - Added pattern field */ @Component(service = RESTResource.class) @JaxrsResource @@ -520,6 +521,7 @@ private PageDTO createPageBean(String sitemapName, @Nullable String title, @Null bean.valuecolor = convertItemValueColor(itemUIRegistry.getValueColor(widget), itemState); bean.iconcolor = convertItemValueColor(itemUIRegistry.getIconColor(widget), itemState); bean.label = itemUIRegistry.getLabel(widget); + bean.pattern = itemUIRegistry.getFormatPattern(widget); bean.type = widget.eClass().getName(); bean.visibility = itemUIRegistry.getVisiblity(widget); if (widget instanceof LinkableWidget linkableWidget) { diff --git a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapWidgetEvent.java b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapWidgetEvent.java index a2ba2536d88..dd52db3ebbb 100644 --- a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapWidgetEvent.java +++ b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapWidgetEvent.java @@ -19,6 +19,7 @@ * * @author Kai Kreuzer - Initial contribution * @author Laurent Garnier - New field iconcolor + * @author Mark Herwege - New field pattern */ public class SitemapWidgetEvent extends SitemapEvent { @@ -26,6 +27,7 @@ public class SitemapWidgetEvent extends SitemapEvent { public String label; public String icon; + public String pattern; public String labelcolor; public String valuecolor; public String iconcolor; diff --git a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/WidgetDTO.java b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/WidgetDTO.java index db47ddd27e8..e13ec0beca2 100644 --- a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/WidgetDTO.java +++ b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/WidgetDTO.java @@ -24,6 +24,7 @@ * @author Kai Kreuzer - Initial contribution * @author Chris Jackson - Initial contribution * @author Laurent Garnier - New field iconcolor + * @author Mark herwege - New field pattern */ public class WidgetDTO { @@ -38,6 +39,8 @@ public class WidgetDTO { public String valuecolor; public String iconcolor; + public String pattern; + // widget-specific attributes public final List mappings = new ArrayList<>(); public Boolean switchSupport; diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java index 4be4185cddc..ebe82bb5ad7 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java @@ -108,6 +108,7 @@ * @author Stefan Triller - Method to convert a state into something a sitemap entity can understand * @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType * @author Laurent Garnier - new method getIconColor + * @author Mark Herwege - new method getFormatPattern(widget), clean pattern */ @NonNullByDefault @Component(immediate = true, configurationPid = "org.openhab.sitemap", // @@ -121,9 +122,9 @@ public class ItemUIRegistryImpl implements ItemUIRegistry { protected static final Pattern EXTRACT_TRANSFORM_FUNCTION_PATTERN = Pattern.compile("(.*?)\\((.*)\\):(.*)"); /* RegEx to identify format patterns. See java.util.Formatter#formatSpecifier (without the '%' at the very end). */ - protected static final String IDENTIFY_FORMAT_PATTERN_PATTERN = "%((unit%)|((\\d+\\$)?([-#+ 0,(<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z])))"; + protected static final String IDENTIFY_FORMAT_PATTERN_PATTERN = "%(?:(unit%)|(?:(?:\\d+\\$)?(?:[-#+ 0,(<]*)?(?:\\d+)?(?:\\.\\d+)?(?:[tT])?(?:[a-zA-Z])))"; + private static final Pattern FORMAT_PATTERN = Pattern.compile("(?:^|[^%])" + IDENTIFY_FORMAT_PATTERN_PATTERN); - private static final Pattern LABEL_PATTERN = Pattern.compile(".*?\\[.*? (.*?)]"); private static final int MAX_BUTTONS = 4; private static final String DEFAULT_SORTING = "NONE"; @@ -331,10 +332,14 @@ private Switch createPlayerButtons() { String labelMappedOption = null; State state = null; StateDescription stateDescription = null; - String formatPattern = getFormatPattern(label); + String formatPattern = getFormatPattern(w); + + if (formatPattern != null && label.indexOf("[") < 0) { + label = label + " [" + formatPattern + "]"; + } // now insert the value, if the state is a string or decimal value and there is some formatting pattern defined - // in the label (i.e. it contains at least a %) + // in the label or state description (i.e. it contains at least a %) try { final Item item = getItem(itemName); @@ -348,13 +353,8 @@ private Switch createPlayerButtons() { // returned StateDescription. What is expected is the display of a value using the pattern // provided by the channel state description provider. stateDescription = item.getStateDescription(); - if (formatPattern == null && stateDescription != null && stateDescription.getPattern() != null) { - label = label + " [" + stateDescription.getPattern() + "]"; - } - String updatedPattern = getFormatPattern(label); - if (updatedPattern != null) { - formatPattern = updatedPattern; + if (formatPattern != null) { state = item.getState(); if (formatPattern.contains("%d")) { @@ -455,7 +455,10 @@ private Switch createPlayerButtons() { } label = label.trim(); - label = label.substring(0, label.indexOf("[") + 1) + formatPattern + "]"; + int index = label.indexOf("["); + if (index >= 0) { + label = label.substring(0, label.indexOf("[") + 1) + formatPattern + "]"; + } } } @@ -463,7 +466,7 @@ private Switch createPlayerButtons() { } private QuantityType convertStateToWidgetUnit(QuantityType quantityState, Widget w) { - Unit widgetUnit = UnitUtils.parseUnit(getFormatPattern(w.getLabel())); + Unit widgetUnit = UnitUtils.parseUnit(getFormatPattern(w)); if (widgetUnit != null && !widgetUnit.equals(quantityState.getUnit())) { return Objects.requireNonNullElse(quantityState.toInvertibleUnit(widgetUnit), quantityState); } @@ -471,6 +474,54 @@ private QuantityType convertStateToWidgetUnit(QuantityType quantityState, return quantityState; } + @Override + public @Nullable String getFormatPattern(Widget w) { + String label = getLabelFromWidget(w); + String pattern = getFormatPattern(label); + String itemName = w.getItem(); + try { + Item item = getItem(itemName); + if (pattern == null) { + StateDescription stateDescription = item.getStateDescription(); + if (stateDescription != null) { + pattern = stateDescription.getPattern(); + } + } + + if (pattern == null) { + return null; + } + + // remove last part of pattern, after unit, if it exists, as this is not valid and creates problems with + // updates + if (item instanceof NumberItem && (((NumberItem) item).getDimension() != null)) { + Matcher m = FORMAT_PATTERN.matcher(pattern); + int matcherEnd = 0; + while (m.find() && m.group(1) == null) { + matcherEnd = m.end(); + } + String unit = pattern.substring(matcherEnd).trim(); + String postfix = ""; + int unitEnd = unit.indexOf(" "); + if (unitEnd > -1) { + postfix = unit.substring(unitEnd + 1).trim(); + unit = unit.substring(0, unitEnd); + } + if (!postfix.isBlank()) { + logger.warn( + "Item '{}' with unit, nothing allowed after unit in label pattern '{}', dropping postfix", + itemName, pattern); + } + pattern = pattern.substring(0, matcherEnd) + (!unit.isBlank() ? " " + unit : ""); + } + + } catch (ItemNotFoundException e) { + logger.error("Cannot retrieve item '{}' for widget {}", itemName, w.eClass().getInstanceTypeName()); + } + + return pattern; + } + private @Nullable String getFormatPattern(@Nullable String label) { if (label == null) { return null; @@ -1325,12 +1376,13 @@ public void removeRegistryHook(RegistryHook hook) { // we require the item to define a dimension, otherwise no unit will be reported to the UIs. if (item instanceof NumberItem numberItem && numberItem.getDimension() != null) { - if (w.getLabel() == null) { + String pattern = getFormatPattern(w); + if (pattern == null || pattern.isBlank()) { // if no Label was assigned to the Widget we fallback to the items unit return numberItem.getUnitSymbol(); } - String unit = getUnitFromLabel(w.getLabel()); + String unit = getUnitFromPattern(pattern); if (!UnitUtils.UNIT_PLACEHOLDER.equals(unit)) { return unit; } @@ -1354,14 +1406,13 @@ public void removeRegistryHook(RegistryHook hook) { return state; } - private @Nullable String getUnitFromLabel(@Nullable String label) { - if (label == null || label.isBlank()) { + private @Nullable String getUnitFromPattern(@Nullable String format) { + if (format == null || format.isBlank()) { return null; } - Matcher m = LABEL_PATTERN.matcher(label); - if (m.matches()) { - return m.group(1); - } - return null; + int index = format.lastIndexOf(" "); + String unit = index > 0 ? format.substring(index + 1) : null; + unit = UnitUtils.UNIT_PERCENT_FORMAT_STRING.equals(unit) ? "%" : unit; + return unit; } } diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/items/ItemUIRegistry.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/items/ItemUIRegistry.java index 998a11d3c4c..a979543d4cf 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/items/ItemUIRegistry.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/items/ItemUIRegistry.java @@ -34,6 +34,7 @@ * @author Kai Kreuzer - Initial contribution * @author Chris Jackson - Initial contribution * @author Laurent Garnier - new method getIconColor + * @author Mark Herwege - new method getFormatPattern */ @NonNullByDefault public interface ItemUIRegistry extends ItemRegistry, ItemUIProvider { @@ -130,6 +131,15 @@ public interface ItemUIRegistry extends ItemRegistry, ItemUIProvider { @Nullable EObject getParent(Widget w); + /** + * Gets the format pattern for the widget value, retrieved from widget label, item label or item state description + * + * @param w Widget + * @return String with the format pattern + */ + @Nullable + String getFormatPattern(Widget w); + /** * Gets the label color for the widget. Checks conditional statements to * find the color based on the item value From 8fb8ab5f9e6eb2755550bceda66f4461abb11647 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Thu, 1 Jun 2023 14:38:17 +0200 Subject: [PATCH 2/7] Add unit fields to sitemap REST Signed-off-by: Mark Herwege --- .../io/rest/core/item/EnrichedGroupItemDTO.java | 4 ++-- .../core/io/rest/core/item/EnrichedItemDTO.java | 5 ++++- .../io/rest/core/item/EnrichedItemDTOMapper.java | 9 +++++++-- .../rest/sitemap/internal/PageChangeListener.java | 2 -- .../io/rest/sitemap/internal/SitemapResource.java | 3 ++- .../rest/sitemap/internal/SitemapWidgetEvent.java | 2 -- .../core/io/rest/sitemap/internal/WidgetDTO.java | 3 ++- .../core/ui/internal/items/ItemUIRegistryImpl.java | 13 ++++++++----- 8 files changed, 25 insertions(+), 16 deletions(-) diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedGroupItemDTO.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedGroupItemDTO.java index f35fc14648b..4604bf4aa74 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedGroupItemDTO.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedGroupItemDTO.java @@ -25,8 +25,8 @@ public class EnrichedGroupItemDTO extends EnrichedItemDTO { public EnrichedGroupItemDTO(ItemDTO itemDTO, EnrichedItemDTO[] members, String link, String state, - String transformedState, StateDescription stateDescription) { - super(itemDTO, link, state, transformedState, stateDescription, null); + String transformedState, StateDescription stateDescription, String unitSymbol) { + super(itemDTO, link, state, transformedState, stateDescription, null, unitSymbol); this.members = members; this.groupType = ((GroupItemDTO) itemDTO).groupType; this.function = ((GroupItemDTO) itemDTO).function; diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTO.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTO.java index 5a9da86eafd..36f5b0d4ff2 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTO.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTO.java @@ -24,6 +24,7 @@ * * @author Dennis Nobel - Initial contribution * @author Kai Kreuzer - Added metadata + * @author Mark Herwege - Added default unit symbol */ public class EnrichedItemDTO extends ItemDTO { @@ -32,11 +33,12 @@ public class EnrichedItemDTO extends ItemDTO { public String transformedState; public StateDescription stateDescription; public CommandDescription commandDescription; + public String unitSymbol; public Map metadata; public Boolean editable; public EnrichedItemDTO(ItemDTO itemDTO, String link, String state, String transformedState, - StateDescription stateDescription, CommandDescription commandDescription) { + StateDescription stateDescription, CommandDescription commandDescription, String unitSymbol) { this.type = itemDTO.type; this.name = itemDTO.name; this.label = itemDTO.label; @@ -48,5 +50,6 @@ public EnrichedItemDTO(ItemDTO itemDTO, String link, String state, String transf this.transformedState = transformedState; this.stateDescription = stateDescription; this.commandDescription = commandDescription; + this.unitSymbol = unitSymbol; } } diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTOMapper.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTOMapper.java index 2036e5b853f..94a4b85c122 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTOMapper.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTOMapper.java @@ -27,6 +27,7 @@ import org.openhab.core.items.Item; import org.openhab.core.items.dto.ItemDTO; import org.openhab.core.items.dto.ItemDTOMapper; +import org.openhab.core.library.items.NumberItem; import org.openhab.core.transform.TransformationException; import org.openhab.core.transform.TransformationHelper; import org.openhab.core.types.StateDescription; @@ -93,6 +94,10 @@ private static EnrichedItemDTO map(Item item, ItemDTO itemDTO, boolean drillDown EnrichedItemDTO enrichedItemDTO; + String unitSymbol = null; + if (item instanceof NumberItem numberItem) { + unitSymbol = numberItem.getUnitSymbol(); + } if (item instanceof GroupItem groupItem) { EnrichedItemDTO[] memberDTOs; if (drillDown) { @@ -111,10 +116,10 @@ private static EnrichedItemDTO map(Item item, ItemDTO itemDTO, boolean drillDown memberDTOs = new EnrichedItemDTO[0]; } enrichedItemDTO = new EnrichedGroupItemDTO(itemDTO, memberDTOs, link, state, transformedState, - stateDescription); + stateDescription, unitSymbol); } else { enrichedItemDTO = new EnrichedItemDTO(itemDTO, link, state, transformedState, stateDescription, - item.getCommandDescription(locale)); + item.getCommandDescription(locale), unitSymbol); } return enrichedItemDTO; diff --git a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/PageChangeListener.java b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/PageChangeListener.java index 976e3f6467f..3252af2f6bd 100644 --- a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/PageChangeListener.java +++ b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/PageChangeListener.java @@ -44,7 +44,6 @@ * * @author Kai Kreuzer - Initial contribution * @author Laurent Garnier - Added support for icon color - * @author Mark Herwege - Added format pattern field */ public class PageChangeListener implements StateChangeListener { @@ -239,7 +238,6 @@ private SitemapWidgetEvent constructSitemapEventForWidget(Item item, State state event.sitemapName = sitemapName; event.pageId = pageId; event.label = itemUIRegistry.getLabel(widget); - event.pattern = itemUIRegistry.getFormatPattern(widget); event.widgetId = itemUIRegistry.getWidgetId(widget); event.visibility = itemUIRegistry.getVisiblity(widget); event.descriptionChanged = false; diff --git a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java index 10f47b98a63..84d3823ff44 100644 --- a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java +++ b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java @@ -125,7 +125,7 @@ * @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification * @author Wouter Born - Migrated to OpenAPI annotations * @author Laurent Garnier - Added support for icon color - * @author Mark Herwege - Added pattern field + * @author Mark Herwege - Added pattern and unit fields */ @Component(service = RESTResource.class) @JaxrsResource @@ -522,6 +522,7 @@ private PageDTO createPageBean(String sitemapName, @Nullable String title, @Null bean.iconcolor = convertItemValueColor(itemUIRegistry.getIconColor(widget), itemState); bean.label = itemUIRegistry.getLabel(widget); bean.pattern = itemUIRegistry.getFormatPattern(widget); + bean.unit = itemUIRegistry.getUnitForWidget(widget); bean.type = widget.eClass().getName(); bean.visibility = itemUIRegistry.getVisiblity(widget); if (widget instanceof LinkableWidget linkableWidget) { diff --git a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapWidgetEvent.java b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapWidgetEvent.java index dd52db3ebbb..a2ba2536d88 100644 --- a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapWidgetEvent.java +++ b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapWidgetEvent.java @@ -19,7 +19,6 @@ * * @author Kai Kreuzer - Initial contribution * @author Laurent Garnier - New field iconcolor - * @author Mark Herwege - New field pattern */ public class SitemapWidgetEvent extends SitemapEvent { @@ -27,7 +26,6 @@ public class SitemapWidgetEvent extends SitemapEvent { public String label; public String icon; - public String pattern; public String labelcolor; public String valuecolor; public String iconcolor; diff --git a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/WidgetDTO.java b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/WidgetDTO.java index e13ec0beca2..c9dc713b082 100644 --- a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/WidgetDTO.java +++ b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/WidgetDTO.java @@ -24,7 +24,7 @@ * @author Kai Kreuzer - Initial contribution * @author Chris Jackson - Initial contribution * @author Laurent Garnier - New field iconcolor - * @author Mark herwege - New field pattern + * @author Mark herwege - New fields pattern, unit */ public class WidgetDTO { @@ -40,6 +40,7 @@ public class WidgetDTO { public String iconcolor; public String pattern; + public String unit; // widget-specific attributes public final List mappings = new ArrayList<>(); diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java index ebe82bb5ad7..b30e215dcd9 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java @@ -480,8 +480,11 @@ private QuantityType convertStateToWidgetUnit(QuantityType quantityState, String pattern = getFormatPattern(label); String itemName = w.getItem(); try { - Item item = getItem(itemName); - if (pattern == null) { + Item item = null; + if (itemName != null && !itemName.isBlank()) { + item = getItem(itemName); + } + if (item != null && pattern == null) { StateDescription stateDescription = item.getStateDescription(); if (stateDescription != null) { pattern = stateDescription.getPattern(); @@ -678,8 +681,8 @@ private String transform(String label, boolean matchTransform, @Nullable String State returnState = null; State itemState = i.getState(); - if (itemState instanceof QuantityType type) { - itemState = convertStateToWidgetUnit(type, w); + if (itemState instanceof QuantityType quantityTypeState) { + itemState = convertStateToWidgetUnit(quantityTypeState, w); } if (w instanceof Switch && i instanceof RollershutterItem) { @@ -688,7 +691,7 @@ private String transform(String label, boolean matchTransform, @Nullable String } else if (w instanceof Slider) { if (i.getAcceptedDataTypes().contains(PercentType.class)) { returnState = itemState.as(PercentType.class); - } else { + } else if (!(itemState instanceof QuantityType)) { returnState = itemState.as(DecimalType.class); } } else if (w instanceof Switch sw) { From 8cfac2c75841e94f2be3e1a416d92a5a022cf1b1 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Tue, 6 Jun 2023 08:57:56 +0200 Subject: [PATCH 3/7] Java 17 syntax improvement Signed-off-by: Mark Herwege --- .../org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java index b30e215dcd9..382f6d681a8 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java @@ -497,7 +497,7 @@ private QuantityType convertStateToWidgetUnit(QuantityType quantityState, // remove last part of pattern, after unit, if it exists, as this is not valid and creates problems with // updates - if (item instanceof NumberItem && (((NumberItem) item).getDimension() != null)) { + if (item instanceof NumberItem numberItem && numberItem.getDimension() != null) { Matcher m = FORMAT_PATTERN.matcher(pattern); int matcherEnd = 0; while (m.find() && m.group(1) == null) { From f5d319f0f2d26e1b9ec86eb30eb3c8806759f480 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Sun, 11 Jun 2023 16:02:00 +0200 Subject: [PATCH 4/7] review feedback Signed-off-by: Mark Herwege --- .../core/ui/internal/items/ItemUIRegistryImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java index 382f6d681a8..1fb84d10442 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java @@ -371,7 +371,7 @@ private Switch createPlayerButtons() { } } } catch (ItemNotFoundException e) { - logger.error("Cannot retrieve item '{}' for widget {}", itemName, w.eClass().getInstanceTypeName()); + logger.warn("Cannot retrieve item '{}' for widget {}", itemName, w.eClass().getInstanceTypeName()); } boolean considerTransform = false; @@ -457,7 +457,7 @@ private Switch createPlayerButtons() { label = label.trim(); int index = label.indexOf("["); if (index >= 0) { - label = label.substring(0, label.indexOf("[") + 1) + formatPattern + "]"; + label = label.substring(0, index + 1) + formatPattern + "]"; } } } @@ -519,7 +519,7 @@ private QuantityType convertStateToWidgetUnit(QuantityType quantityState, } } catch (ItemNotFoundException e) { - logger.error("Cannot retrieve item '{}' for widget {}", itemName, w.eClass().getInstanceTypeName()); + logger.warn("Cannot retrieve item '{}' for widget {}", itemName, w.eClass().getInstanceTypeName()); } return pattern; @@ -662,7 +662,7 @@ private String transform(String label, boolean matchTransform, @Nullable String Item item = getItem(itemName); return convertState(w, item, item.getState()); } catch (ItemNotFoundException e) { - logger.error("Cannot retrieve item '{}' for widget {}", itemName, w.eClass().getInstanceTypeName()); + logger.warn("Cannot retrieve item '{}' for widget {}", itemName, w.eClass().getInstanceTypeName()); } } return UnDefType.UNDEF; @@ -1262,7 +1262,7 @@ public boolean getVisiblity(Widget w) { try { item = itemRegistry.getItem(itemName); } catch (ItemNotFoundException e) { - logger.error("Cannot retrieve visibility item {} for widget {}", rule.getItem(), + logger.warn("Cannot retrieve visibility item {} for widget {}", rule.getItem(), w.eClass().getInstanceTypeName()); // Default to visible! @@ -1393,7 +1393,7 @@ public void removeRegistryHook(RegistryHook hook) { return numberItem.getUnitSymbol(); } } catch (ItemNotFoundException e) { - logger.debug("Failed to retrieve item during widget rendering: {}", e.getMessage()); + logger.warn("Failed to retrieve item during widget rendering, item does not exist: {}", e.getMessage()); } return ""; From 2d6585adff24f2f23641706107501499e9d9f009 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Tue, 13 Jun 2023 08:58:21 +0200 Subject: [PATCH 5/7] revert item REST changes Signed-off-by: Mark Herwege --- .../core/io/rest/core/item/EnrichedGroupItemDTO.java | 4 ++-- .../openhab/core/io/rest/core/item/EnrichedItemDTO.java | 5 +---- .../core/io/rest/core/item/EnrichedItemDTOMapper.java | 9 ++------- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedGroupItemDTO.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedGroupItemDTO.java index 4604bf4aa74..f35fc14648b 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedGroupItemDTO.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedGroupItemDTO.java @@ -25,8 +25,8 @@ public class EnrichedGroupItemDTO extends EnrichedItemDTO { public EnrichedGroupItemDTO(ItemDTO itemDTO, EnrichedItemDTO[] members, String link, String state, - String transformedState, StateDescription stateDescription, String unitSymbol) { - super(itemDTO, link, state, transformedState, stateDescription, null, unitSymbol); + String transformedState, StateDescription stateDescription) { + super(itemDTO, link, state, transformedState, stateDescription, null); this.members = members; this.groupType = ((GroupItemDTO) itemDTO).groupType; this.function = ((GroupItemDTO) itemDTO).function; diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTO.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTO.java index 36f5b0d4ff2..5a9da86eafd 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTO.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTO.java @@ -24,7 +24,6 @@ * * @author Dennis Nobel - Initial contribution * @author Kai Kreuzer - Added metadata - * @author Mark Herwege - Added default unit symbol */ public class EnrichedItemDTO extends ItemDTO { @@ -33,12 +32,11 @@ public class EnrichedItemDTO extends ItemDTO { public String transformedState; public StateDescription stateDescription; public CommandDescription commandDescription; - public String unitSymbol; public Map metadata; public Boolean editable; public EnrichedItemDTO(ItemDTO itemDTO, String link, String state, String transformedState, - StateDescription stateDescription, CommandDescription commandDescription, String unitSymbol) { + StateDescription stateDescription, CommandDescription commandDescription) { this.type = itemDTO.type; this.name = itemDTO.name; this.label = itemDTO.label; @@ -50,6 +48,5 @@ public EnrichedItemDTO(ItemDTO itemDTO, String link, String state, String transf this.transformedState = transformedState; this.stateDescription = stateDescription; this.commandDescription = commandDescription; - this.unitSymbol = unitSymbol; } } diff --git a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTOMapper.java b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTOMapper.java index 94a4b85c122..2036e5b853f 100644 --- a/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTOMapper.java +++ b/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTOMapper.java @@ -27,7 +27,6 @@ import org.openhab.core.items.Item; import org.openhab.core.items.dto.ItemDTO; import org.openhab.core.items.dto.ItemDTOMapper; -import org.openhab.core.library.items.NumberItem; import org.openhab.core.transform.TransformationException; import org.openhab.core.transform.TransformationHelper; import org.openhab.core.types.StateDescription; @@ -94,10 +93,6 @@ private static EnrichedItemDTO map(Item item, ItemDTO itemDTO, boolean drillDown EnrichedItemDTO enrichedItemDTO; - String unitSymbol = null; - if (item instanceof NumberItem numberItem) { - unitSymbol = numberItem.getUnitSymbol(); - } if (item instanceof GroupItem groupItem) { EnrichedItemDTO[] memberDTOs; if (drillDown) { @@ -116,10 +111,10 @@ private static EnrichedItemDTO map(Item item, ItemDTO itemDTO, boolean drillDown memberDTOs = new EnrichedItemDTO[0]; } enrichedItemDTO = new EnrichedGroupItemDTO(itemDTO, memberDTOs, link, state, transformedState, - stateDescription, unitSymbol); + stateDescription); } else { enrichedItemDTO = new EnrichedItemDTO(itemDTO, link, state, transformedState, stateDescription, - item.getCommandDescription(locale), unitSymbol); + item.getCommandDescription(locale)); } return enrichedItemDTO; From ca7fff244e6a91c965dffc54ad05135a3e0906a5 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Sun, 18 Jun 2023 16:17:24 +0200 Subject: [PATCH 6/7] review feedback Signed-off-by: Mark Herwege --- .../org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java index 1fb84d10442..733ba3badd9 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java @@ -517,7 +517,6 @@ private QuantityType convertStateToWidgetUnit(QuantityType quantityState, } pattern = pattern.substring(0, matcherEnd) + (!unit.isBlank() ? " " + unit : ""); } - } catch (ItemNotFoundException e) { logger.warn("Cannot retrieve item '{}' for widget {}", itemName, w.eClass().getInstanceTypeName()); } From d7ce9030d0bbe0612f90815d7c270cb3d4e32553 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Mon, 19 Jun 2023 09:10:35 +0200 Subject: [PATCH 7/7] no regex iteration Signed-off-by: Mark Herwege --- .../org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java index 733ba3badd9..d5a69469427 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java @@ -500,7 +500,7 @@ private QuantityType convertStateToWidgetUnit(QuantityType quantityState, if (item instanceof NumberItem numberItem && numberItem.getDimension() != null) { Matcher m = FORMAT_PATTERN.matcher(pattern); int matcherEnd = 0; - while (m.find() && m.group(1) == null) { + if (m.find() && m.group(1) == null) { matcherEnd = m.end(); } String unit = pattern.substring(matcherEnd).trim();