diff --git a/bundles/org.openhab.persistence.jpa/src/main/java/org/openhab/persistence/jpa/internal/JpaHistoricItem.java b/bundles/org.openhab.persistence.jpa/src/main/java/org/openhab/persistence/jpa/internal/JpaHistoricItem.java index eaee4bb8caa..ec7f7d8a12b 100644 --- a/bundles/org.openhab.persistence.jpa/src/main/java/org/openhab/persistence/jpa/internal/JpaHistoricItem.java +++ b/bundles/org.openhab.persistence.jpa/src/main/java/org/openhab/persistence/jpa/internal/JpaHistoricItem.java @@ -17,11 +17,13 @@ import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import javax.measure.Unit; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.items.Item; import org.openhab.core.library.items.ContactItem; import org.openhab.core.library.items.DateTimeItem; @@ -39,10 +41,13 @@ import org.openhab.core.library.types.PointType; import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.StringListType; import org.openhab.core.library.types.StringType; +import org.openhab.core.library.unit.Units; import org.openhab.core.persistence.HistoricItem; import org.openhab.core.types.State; import org.openhab.core.types.UnDefType; import org.openhab.persistence.jpa.internal.model.JpaPersistentItem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The historic item as returned when querying the service. @@ -52,6 +57,7 @@ import org.openhab.persistence.jpa.internal.model.JpaPersistentItem; */ @NonNullByDefault public class JpaHistoricItem implements HistoricItem { + private static final Logger logger = LoggerFactory.getLogger(JpaHistoricItem.class); private final String name; private final State state; @@ -91,7 +97,8 @@ public class JpaHistoricItem implements HistoricItem { * @return list of historic items */ public static List fromResultList(List jpaQueryResult, Item item) { - return jpaQueryResult.stream().map(pItem -> fromPersistedItem(pItem, item)).collect(Collectors.toList()); + return jpaQueryResult.stream().map(pItem -> fromPersistedItem(pItem, item)).filter(Objects::nonNull) + .map(Objects::requireNonNull).collect(Collectors.toList()); } /** @@ -101,12 +108,26 @@ public class JpaHistoricItem implements HistoricItem { * @param item the source reference Item * @return historic item */ - public static HistoricItem fromPersistedItem(JpaPersistentItem pItem, Item item) { + public static @Nullable HistoricItem fromPersistedItem(JpaPersistentItem pItem, Item item) { State state; if (item instanceof NumberItem numberItem) { Unit unit = numberItem.getUnit(); - double value = Double.parseDouble(pItem.getValue()); - state = (unit == null) ? new DecimalType(value) : new QuantityType<>(value, unit); + QuantityType value = QuantityType.valueOf(pItem.getValue()); + if (unit == null) { + // Item has no unit; drop any persisted unit + state = Objects.requireNonNull(value.as(DecimalType.class)); + } else if (value.getUnit() == Units.ONE) { + // No persisted unit; assume the item's unit + state = new QuantityType<>(value.toBigDecimal(), unit); + } else { + // Ensure we return in the item's unit + state = value.toUnit(unit); + if (state == null) { + logger.warn("Persisted state {} for item {} is incompatible with item's unit {}; ignoring", value, + item.getName(), unit); + return null; + } + } } else if (item instanceof DimmerItem) { state = new PercentType(Integer.parseInt(pItem.getValue())); } else if (item instanceof SwitchItem) {