2 * Copyright (c) 2010-2024 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.binding.mielecloud.internal.handler.channel;
15 import java.math.BigDecimal;
16 import java.text.NumberFormat;
17 import java.util.Locale;
18 import java.util.Optional;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.openhab.binding.mielecloud.internal.webservice.api.Quantity;
22 import org.openhab.core.library.types.DecimalType;
23 import org.openhab.core.library.types.OnOffType;
24 import org.openhab.core.library.types.QuantityType;
25 import org.openhab.core.library.types.StringType;
26 import org.openhab.core.library.unit.SIUnits;
27 import org.openhab.core.types.State;
28 import org.openhab.core.types.UnDefType;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * Utility class handling type conversions from Java types to channel types.
35 * @author Björn Lange - Initial Contribution
38 public final class ChannelTypeUtil {
39 private static final Logger LOGGER = LoggerFactory.getLogger(ChannelTypeUtil.class);
41 private ChannelTypeUtil() {
42 throw new IllegalStateException("ChannelTypeUtil cannot be instantiated.");
46 * Converts an {@link Optional} of {@link String} to {@link State}.
48 public static State stringToState(Optional<String> value) {
49 return value.filter(v -> !v.isEmpty()).filter(v -> !"null".equals(v)).map(v -> (State) new StringType(v))
50 .orElse(UnDefType.UNDEF);
54 * Converts an {@link Optional} of {@link Boolean} to {@link State}.
56 public static State booleanToState(Optional<Boolean> value) {
57 return value.map(v -> (State) OnOffType.from(v)).orElse(UnDefType.UNDEF);
61 * Converts an {@link Optional} of {@link Integer} to {@link State}.
63 public static State intToState(Optional<Integer> value) {
64 return value.map(v -> (State) new DecimalType(new BigDecimal(v))).orElse(UnDefType.UNDEF);
68 * Converts an {@link Optional} of {@link Long} to {@link State}.
70 public static State longToState(Optional<Long> value) {
71 return value.map(v -> (State) new DecimalType(new BigDecimal(v))).orElse(UnDefType.UNDEF);
75 * Converts an {@link Optional} of {@link Integer} to {@link State} representing a temperature.
77 public static State intToTemperatureState(Optional<Integer> value) {
78 // The Miele 3rd Party API always provides temperatures in °C (even if the device uses another unit).
79 return value.map(v -> (State) new QuantityType<>(v, SIUnits.CELSIUS)).orElse(UnDefType.UNDEF);
83 * Converts an {@link Optional} of {@link Quantity} to {@link State}.
85 public static State quantityToState(Optional<Quantity> value) {
86 return value.flatMap(ChannelTypeUtil::formatQuantity).flatMap(ChannelTypeUtil::parseQuantityType)
87 .orElse(UnDefType.UNDEF);
91 * Formats the quantity as "value unit" with the given locale.
93 * @param locale The locale to format with.
94 * @return An {@link Optional} containing the formatted quantity value or an empty {@link Optional} if formatting
95 * for the given locale failed.
97 private static Optional<String> formatQuantity(Quantity quantity) {
98 double value = quantity.getValue();
100 var formatted = NumberFormat.getInstance(Locale.ENGLISH).format(value);
102 var unit = quantity.getUnit();
103 if (unit.isPresent()) {
104 formatted = formatted + " " + unit.get();
107 return Optional.of(formatted);
108 } catch (ArithmeticException e) {
109 LOGGER.warn("Failed to format {}", value, e);
110 return Optional.empty();
115 * Parses a previously formatted {@link Quantity} into a {@link State}.
117 * @param value The quantity value formatted as "value unit".
118 * @return An {@link Optional} containing the parsed {@link State} or an empty {@link Optional} if the quantity
119 * including unit could not be parsed.
121 private static Optional<State> parseQuantityType(String value) {
123 return Optional.of((State) new QuantityType<>(value));
124 } catch (IllegalArgumentException e) {
125 LOGGER.warn("Failed to convert {} to quantity: {}", value, e.getMessage(), e);
126 return Optional.empty();