2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.persistence.influxdb.internal;
15 import java.math.BigDecimal;
16 import java.time.Instant;
17 import java.time.ZonedDateTime;
18 import java.util.TimeZone;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.core.items.GroupItem;
23 import org.openhab.core.items.Item;
24 import org.openhab.core.items.ItemNotFoundException;
25 import org.openhab.core.items.ItemRegistry;
26 import org.openhab.core.library.items.ColorItem;
27 import org.openhab.core.library.items.ContactItem;
28 import org.openhab.core.library.items.DateTimeItem;
29 import org.openhab.core.library.items.DimmerItem;
30 import org.openhab.core.library.items.LocationItem;
31 import org.openhab.core.library.items.NumberItem;
32 import org.openhab.core.library.items.RollershutterItem;
33 import org.openhab.core.library.items.SwitchItem;
34 import org.openhab.core.library.types.DateTimeType;
35 import org.openhab.core.library.types.DecimalType;
36 import org.openhab.core.library.types.HSBType;
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.StringType;
43 import org.openhab.core.types.State;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
48 * Conversion logic between openHAB {@link State} types and InfluxDB store types
50 * @author Joan Pujol Espinar - Initial contribution, based on previous work from Theo Weiss and Dominik Vorreiter
53 public class InfluxDBStateConvertUtils {
54 static final Number DIGITAL_VALUE_OFF = 0; // Visible for testing
55 static final Number DIGITAL_VALUE_ON = 1; // Visible for testing
56 private static Logger logger = LoggerFactory.getLogger(InfluxDBStateConvertUtils.class);
59 * Converts {@link State} to objects fitting into influxdb values.
61 * @param state to be converted
62 * @return integer or double value for DecimalType, 0 or 1 for OnOffType and OpenClosedType,
63 * integer for DateTimeType, String for all others
65 public static Object stateToObject(State state) {
67 if (state instanceof HSBType) {
68 value = state.toString();
69 } else if (state instanceof PointType) {
70 value = point2String((PointType) state);
71 } else if (state instanceof DecimalType) {
72 value = ((DecimalType) state).toBigDecimal();
73 } else if (state instanceof QuantityType<?>) {
74 value = ((QuantityType<?>) state).toBigDecimal();
75 } else if (state instanceof OnOffType) {
76 value = state == OnOffType.ON ? DIGITAL_VALUE_ON : DIGITAL_VALUE_OFF;
77 } else if (state instanceof OpenClosedType) {
78 value = state == OpenClosedType.OPEN ? DIGITAL_VALUE_ON : DIGITAL_VALUE_OFF;
79 } else if (state instanceof DateTimeType) {
80 value = ((DateTimeType) state).getZonedDateTime().toInstant().toEpochMilli();
82 value = state.toString();
88 * Converts a value to a {@link State} which is suitable for the given {@link Item}. This is
89 * needed for querying an {@link InfluxDBHistoricItem}.
91 * @param value to be converted to a {@link State}
92 * @param itemName name of the {@link Item} to get the {@link State} for
93 * @return the state of the item represented by the itemName parameter, else the string value of
94 * the Object parameter
96 public static State objectToState(@Nullable Object value, String itemName, @Nullable ItemRegistry itemRegistry) {
98 if (itemRegistry != null) {
100 Item item = itemRegistry.getItem(itemName);
101 state = objectToState(value, item);
102 } catch (ItemNotFoundException e) {
103 logger.info("Could not find item '{}' in registry", itemName);
108 state = new StringType(String.valueOf(value));
114 public static State objectToState(@Nullable Object value, Item itemToSetState) {
115 String valueStr = String.valueOf(value);
118 Item item = itemToSetState;
119 if (item instanceof GroupItem) {
120 item = ((GroupItem) item).getBaseItem();
122 if (item instanceof ColorItem) {
123 return new HSBType(valueStr);
124 } else if (item instanceof LocationItem) {
125 return new PointType(valueStr);
126 } else if (item instanceof NumberItem) {
127 return new DecimalType(valueStr);
128 } else if (item instanceof DimmerItem) {
129 return new PercentType(valueStr);
130 } else if (item instanceof SwitchItem) {
131 return toBoolean(valueStr) ? OnOffType.ON : OnOffType.OFF;
132 } else if (item instanceof ContactItem) {
133 return toBoolean(valueStr) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
134 } else if (item instanceof RollershutterItem) {
135 return new PercentType(valueStr);
136 } else if (item instanceof DateTimeItem) {
137 Instant i = Instant.ofEpochMilli(new BigDecimal(valueStr).longValue());
138 ZonedDateTime z = ZonedDateTime.ofInstant(i, TimeZone.getDefault().toZoneId());
139 return new DateTimeType(z);
141 return new StringType(valueStr);
145 private static boolean toBoolean(@Nullable Object object) {
146 if (object instanceof Boolean) {
147 return (Boolean) object;
148 } else if (object != null) {
149 if ("1".equals(object) || "1.0".equals(object)) {
152 return Boolean.valueOf(String.valueOf(object));
159 private static String point2String(PointType point) {
160 StringBuilder buf = new StringBuilder();
161 buf.append(point.getLatitude().toString());
163 buf.append(point.getLongitude().toString());
164 if (!point.getAltitude().equals(DecimalType.ZERO)) {
166 buf.append(point.getAltitude().toString());
168 return buf.toString(); // latitude, longitude, altitude