]> git.basschouten.com Git - openhab-addons.git/blob
755412dc902f54d680c6d38465aec6b86298383c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.influxdb.internal;
14
15 import java.math.BigDecimal;
16 import java.time.Instant;
17 import java.time.ZonedDateTime;
18 import java.util.TimeZone;
19
20 import javax.measure.Unit;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.core.items.GroupItem;
25 import org.openhab.core.items.Item;
26 import org.openhab.core.items.ItemNotFoundException;
27 import org.openhab.core.items.ItemRegistry;
28 import org.openhab.core.library.items.ColorItem;
29 import org.openhab.core.library.items.ContactItem;
30 import org.openhab.core.library.items.DateTimeItem;
31 import org.openhab.core.library.items.DimmerItem;
32 import org.openhab.core.library.items.ImageItem;
33 import org.openhab.core.library.items.LocationItem;
34 import org.openhab.core.library.items.NumberItem;
35 import org.openhab.core.library.items.PlayerItem;
36 import org.openhab.core.library.items.RollershutterItem;
37 import org.openhab.core.library.items.SwitchItem;
38 import org.openhab.core.library.types.DateTimeType;
39 import org.openhab.core.library.types.DecimalType;
40 import org.openhab.core.library.types.HSBType;
41 import org.openhab.core.library.types.OnOffType;
42 import org.openhab.core.library.types.OpenClosedType;
43 import org.openhab.core.library.types.PercentType;
44 import org.openhab.core.library.types.PlayPauseType;
45 import org.openhab.core.library.types.PointType;
46 import org.openhab.core.library.types.QuantityType;
47 import org.openhab.core.library.types.RawType;
48 import org.openhab.core.library.types.RewindFastforwardType;
49 import org.openhab.core.library.types.StringType;
50 import org.openhab.core.types.State;
51 import org.openhab.core.types.UnDefType;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55 /**
56  * Conversion logic between openHAB {@link State} types and InfluxDB store types
57  *
58  * @author Joan Pujol Espinar - Initial contribution, based on previous work from Theo Weiss and Dominik Vorreiter
59  */
60 @NonNullByDefault
61 public class InfluxDBStateConvertUtils {
62     static final Number DIGITAL_VALUE_OFF = 0; // Visible for testing
63     static final Number DIGITAL_VALUE_ON = 1; // Visible for testing
64     private static final Logger LOGGER = LoggerFactory.getLogger(InfluxDBStateConvertUtils.class);
65
66     /**
67      * Converts {@link State} to objects fitting into influxdb values.
68      *
69      * @param state to be converted
70      * @return integer or double value for DecimalType, 0 or 1 for OnOffType and OpenClosedType,
71      *         integer for DateTimeType, String for all others
72      */
73     public static Object stateToObject(State state) {
74         Object value;
75         if (state instanceof HSBType) {
76             value = state.toString();
77         } else if (state instanceof PointType) {
78             value = state.toString();
79         } else if (state instanceof DecimalType type) {
80             value = type.toBigDecimal();
81         } else if (state instanceof QuantityType<?> type) {
82             value = type.toBigDecimal();
83         } else if (state instanceof OnOffType) {
84             value = state == OnOffType.ON ? DIGITAL_VALUE_ON : DIGITAL_VALUE_OFF;
85         } else if (state instanceof OpenClosedType) {
86             value = state == OpenClosedType.OPEN ? DIGITAL_VALUE_ON : DIGITAL_VALUE_OFF;
87         } else if (state instanceof DateTimeType type) {
88             value = type.getZonedDateTime().toInstant().toEpochMilli();
89         } else {
90             value = state.toFullString();
91         }
92         return value;
93     }
94
95     /**
96      * Converts a value to a {@link State} which is suitable for the given {@link Item}. This is
97      * needed for querying an {@link InfluxDBHistoricItem}.
98      *
99      * @param value to be converted to a {@link State}
100      * @param itemName name of the {@link Item} to get the {@link State} for
101      * @return the state of the item represented by the itemName parameter, else the string value of
102      *         the Object parameter
103      */
104     public static State objectToState(Object value, String itemName, ItemRegistry itemRegistry) {
105         try {
106             Item item = itemRegistry.getItem(itemName);
107             return objectToState(value, item);
108         } catch (ItemNotFoundException e) {
109             LOGGER.info("Could not find item '{}' in registry", itemName);
110         }
111
112         return new StringType(String.valueOf(value));
113     }
114
115     public static State objectToState(@Nullable Object value, Item itemToSetState) {
116         String valueStr = String.valueOf(value);
117
118         @Nullable
119         Item item = itemToSetState;
120         if (item instanceof GroupItem groupItem) {
121             item = groupItem.getBaseItem();
122         }
123         if (item instanceof ColorItem) {
124             return new HSBType(valueStr);
125         } else if (item instanceof LocationItem) {
126             return new PointType(valueStr);
127         } else if (item instanceof NumberItem numberItem) {
128             Unit<?> unit = numberItem.getUnit();
129             if (unit == null) {
130                 return new DecimalType(valueStr);
131             } else {
132                 return new QuantityType<>(new BigDecimal(valueStr), unit);
133             }
134         } else if (item instanceof DimmerItem) {
135             return new PercentType(valueStr);
136         } else if (item instanceof SwitchItem) {
137             return OnOffType.from(toBoolean(valueStr));
138         } else if (item instanceof ContactItem) {
139             return toBoolean(valueStr) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
140         } else if (item instanceof RollershutterItem) {
141             return new PercentType(valueStr);
142         } else if (item instanceof DateTimeItem) {
143             Instant i = Instant.ofEpochMilli(new BigDecimal(valueStr).longValue());
144             ZonedDateTime z = ZonedDateTime.ofInstant(i, TimeZone.getDefault().toZoneId());
145             return new DateTimeType(z);
146         } else if (item instanceof PlayerItem) {
147             try {
148                 return PlayPauseType.valueOf(valueStr);
149             } catch (IllegalArgumentException ignored) {
150             }
151             try {
152                 return RewindFastforwardType.valueOf(valueStr);
153             } catch (IllegalArgumentException ignored) {
154             }
155         } else if (item instanceof ImageItem) {
156             return RawType.valueOf(valueStr);
157         } else {
158             return new StringType(valueStr);
159         }
160         return UnDefType.UNDEF;
161     }
162
163     private static boolean toBoolean(@Nullable Object object) {
164         if (object instanceof Boolean boolean1) {
165             return boolean1;
166         } else if (object != null) {
167             if ("1".equals(object) || "1.0".equals(object)) {
168                 return true;
169             } else {
170                 return Boolean.parseBoolean(String.valueOf(object));
171             }
172         } else {
173             return false;
174         }
175     }
176 }