]> git.basschouten.com Git - openhab-addons.git/blob
ec7f7d8a12b4b4b2b8844c5790cb759f33806068
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.persistence.jpa.internal;
14
15 import java.text.DateFormat;
16 import java.time.Instant;
17 import java.time.ZoneId;
18 import java.time.ZonedDateTime;
19 import java.util.List;
20 import java.util.Objects;
21 import java.util.stream.Collectors;
22
23 import javax.measure.Unit;
24
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.openhab.core.items.Item;
28 import org.openhab.core.library.items.ContactItem;
29 import org.openhab.core.library.items.DateTimeItem;
30 import org.openhab.core.library.items.DimmerItem;
31 import org.openhab.core.library.items.LocationItem;
32 import org.openhab.core.library.items.NumberItem;
33 import org.openhab.core.library.items.RollershutterItem;
34 import org.openhab.core.library.items.SwitchItem;
35 import org.openhab.core.library.types.DateTimeType;
36 import org.openhab.core.library.types.DecimalType;
37 import org.openhab.core.library.types.OnOffType;
38 import org.openhab.core.library.types.OpenClosedType;
39 import org.openhab.core.library.types.PercentType;
40 import org.openhab.core.library.types.PointType;
41 import org.openhab.core.library.types.QuantityType;
42 import org.openhab.core.library.types.StringListType;
43 import org.openhab.core.library.types.StringType;
44 import org.openhab.core.library.unit.Units;
45 import org.openhab.core.persistence.HistoricItem;
46 import org.openhab.core.types.State;
47 import org.openhab.core.types.UnDefType;
48 import org.openhab.persistence.jpa.internal.model.JpaPersistentItem;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 /**
53  * The historic item as returned when querying the service.
54  *
55  * @author Manfred Bergmann - Initial contribution
56  *
57  */
58 @NonNullByDefault
59 public class JpaHistoricItem implements HistoricItem {
60     private static final Logger logger = LoggerFactory.getLogger(JpaHistoricItem.class);
61
62     private final String name;
63     private final State state;
64     private final ZonedDateTime timestamp;
65
66     public JpaHistoricItem(String name, State state, ZonedDateTime timestamp) {
67         this.name = name;
68         this.state = state;
69         this.timestamp = timestamp;
70     }
71
72     @Override
73     public String getName() {
74         return name;
75     }
76
77     @Override
78     public ZonedDateTime getTimestamp() {
79         return timestamp;
80     }
81
82     @Override
83     public State getState() {
84         return state;
85     }
86
87     @Override
88     public String toString() {
89         return DateFormat.getDateTimeInstance().format(timestamp) + ": " + name + " -> " + state.toString();
90     }
91
92     /**
93      * This method maps {@link JpaPersistentItem}s to {@link HistoricItem}s.
94      *
95      * @param jpaQueryResult the result with jpa items
96      * @param item used for query information, like the state (State)
97      * @return list of historic items
98      */
99     public static List<HistoricItem> fromResultList(List<JpaPersistentItem> jpaQueryResult, Item item) {
100         return jpaQueryResult.stream().map(pItem -> fromPersistedItem(pItem, item)).filter(Objects::nonNull)
101                 .map(Objects::requireNonNull).collect(Collectors.toList());
102     }
103
104     /**
105      * Converts the string value of the persisted item to the state of a {@link HistoricItem}.
106      *
107      * @param pItem the persisted {@link JpaPersistentItem}
108      * @param item the source reference Item
109      * @return historic item
110      */
111     public static @Nullable HistoricItem fromPersistedItem(JpaPersistentItem pItem, Item item) {
112         State state;
113         if (item instanceof NumberItem numberItem) {
114             Unit<?> unit = numberItem.getUnit();
115             QuantityType<?> value = QuantityType.valueOf(pItem.getValue());
116             if (unit == null) {
117                 // Item has no unit; drop any persisted unit
118                 state = Objects.requireNonNull(value.as(DecimalType.class));
119             } else if (value.getUnit() == Units.ONE) {
120                 // No persisted unit; assume the item's unit
121                 state = new QuantityType<>(value.toBigDecimal(), unit);
122             } else {
123                 // Ensure we return in the item's unit
124                 state = value.toUnit(unit);
125                 if (state == null) {
126                     logger.warn("Persisted state {} for item {} is incompatible with item's unit {}; ignoring", value,
127                             item.getName(), unit);
128                     return null;
129                 }
130             }
131         } else if (item instanceof DimmerItem) {
132             state = new PercentType(Integer.parseInt(pItem.getValue()));
133         } else if (item instanceof SwitchItem) {
134             state = OnOffType.valueOf(pItem.getValue());
135         } else if (item instanceof ContactItem) {
136             state = OpenClosedType.valueOf(pItem.getValue());
137         } else if (item instanceof RollershutterItem) {
138             state = PercentType.valueOf(pItem.getValue());
139         } else if (item instanceof DateTimeItem) {
140             state = new DateTimeType(ZonedDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(pItem.getValue())),
141                     ZoneId.systemDefault()));
142         } else if (item instanceof LocationItem) {
143             PointType pType = null;
144             String[] comps = pItem.getValue().split(";");
145             if (comps.length >= 2) {
146                 pType = new PointType(new DecimalType(comps[0]), new DecimalType(comps[1]));
147
148                 if (comps.length == 3) {
149                     pType.setAltitude(new DecimalType(comps[2]));
150                 }
151             }
152             state = pType == null ? UnDefType.UNDEF : pType;
153         } else if (item instanceof StringListType) {
154             state = new StringListType(pItem.getValue());
155         } else {
156             state = new StringType(pItem.getValue());
157         }
158
159         return new JpaHistoricItem(item.getName(), state, pItem.getTimestamp());
160     }
161 }