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.nibeuplink.internal.model;
15 import static org.openhab.binding.nibeuplink.internal.NibeUplinkBindingConstants.*;
17 import java.util.HashMap;
20 import javax.measure.Unit;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.openhab.binding.nibeuplink.internal.handler.ChannelProvider;
24 import org.openhab.binding.nibeuplink.internal.handler.ChannelUtil;
25 import org.openhab.core.library.types.DecimalType;
26 import org.openhab.core.library.types.QuantityType;
27 import org.openhab.core.library.unit.MetricPrefix;
28 import org.openhab.core.library.unit.SIUnits;
29 import org.openhab.core.library.unit.Units;
30 import org.openhab.core.thing.Channel;
31 import org.openhab.core.thing.type.ChannelTypeUID;
32 import org.openhab.core.types.State;
33 import org.openhab.core.types.UnDefType;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * transforms the http response into the openhab datamodel (instances of State)
40 * @author Alexander Friese - initial contribution
43 public class DataResponseTransformer {
44 private final Logger logger = LoggerFactory.getLogger(DataResponseTransformer.class);
46 private static final double UNSCALED = 1;
47 private static final double DIV_10 = 0.1;
48 private static final double DIV_100 = 0.01;
50 private final ChannelProvider channelProvider;
52 public DataResponseTransformer(ChannelProvider channelProvider) {
53 this.channelProvider = channelProvider;
56 public Map<Channel, State> transform(DataResponse response) {
57 Map<String, Long> source = response.getValues();
58 Map<Channel, State> result = new HashMap<>(source.size());
60 for (String channelId : source.keySet()) {
61 Long value = source.get(channelId);
63 Channel channel = channelProvider.getSpecificChannel(channelId);
64 if (channel == null) {
65 // This should not happen but we want to get informed about it
66 logger.warn("Channel not found: {}", channelId);
67 } else if (value == null) {
68 logger.debug("null value for channel: {}", channelId);
69 result.put(channel, UnDefType.UNDEF);
71 ChannelTypeUID typeUID = channel.getChannelTypeUID();
72 String type = typeUID == null ? "null" : typeUID.getId();
75 case CHANNEL_TYPE_TEMPERATURE:
76 case CHANNEL_TYPE_START_COOLING_RW:
77 putQuantityType(result, channel, value, DIV_10, SIUnits.CELSIUS);
79 case CHANNEL_TYPE_PRESSURE:
80 putQuantityType(result, channel, value, DIV_10, Units.BAR);
82 case CHANNEL_TYPE_ENERGY:
83 putQuantityType(result, channel, value, DIV_10, MetricPrefix.KILO(Units.WATT_HOUR));
85 case CHANNEL_TYPE_POWER:
86 putQuantityType(result, channel, value, DIV_100, MetricPrefix.KILO(Units.WATT));
88 case CHANNEL_TYPE_SWITCH_RW:
89 case CHANNEL_TYPE_SWITCH:
90 putOnOffType(result, channel, value);
92 case CHANNEL_TYPE_ELECTRIC_CURRENT:
93 putQuantityType(result, channel, value, DIV_10, Units.AMPERE);
95 case CHANNEL_TYPE_TIME_UNSCALED:
96 putQuantityType(result, channel, value, UNSCALED, Units.HOUR);
98 case CHANNEL_TYPE_TIME_SCALE10:
99 putQuantityType(result, channel, value, DIV_10, Units.HOUR);
101 case CHANNEL_TYPE_FREQUENCY_UNSCALED:
102 putQuantityType(result, channel, value, UNSCALED, Units.HERTZ);
104 case CHANNEL_TYPE_FREQUENCY_SCALE10:
105 putQuantityType(result, channel, value, DIV_10, Units.HERTZ);
107 case CHANNEL_TYPE_FLOW:
108 putQuantityType(result, channel, value, DIV_10, Units.LITRE.divide(Units.MINUTE));
110 case CHANNEL_TYPE_SPEED:
111 putQuantityType(result, channel, value, UNSCALED, Units.PERCENT);
113 case CHANNEL_TYPE_NUMBER_SCALE100:
114 putDecimalType(result, channel, value, DIV_100);
116 case CHANNEL_TYPE_NUMBER_SCALE10:
117 case CHANNEL_TYPE_DEGREE_MINUTES_RW:
118 case CHANNEL_TYPE_STOP_HEATING_RW:
119 case CHANNEL_TYPE_STOP_ADD_HEATING_RW:
120 case CHANNEL_TYPE_ROOM_SENSOR_FACTOR_RW:
121 putDecimalType(result, channel, value, DIV_10);
123 case CHANNEL_TYPE_NUMBER_UNSCALED:
124 case CHANNEL_TYPE_DEFROSTING_STATE:
125 case CHANNEL_TYPE_HPAC_STATE:
126 case CHANNEL_TYPE_HW_LUX_RW:
127 case CHANNEL_TYPE_HW_MODE_RW:
128 case CHANNEL_TYPE_FAN_SPEED_RW:
129 case CHANNEL_TYPE_FILTER_TIME_RW:
130 case CHANNEL_TYPE_HEAT_OFFSET_RW:
131 putDecimalType(result, channel, value, UNSCALED);
134 logger.warn("could not handle unknown type {}, channel {}, value {}", type, channel.getUID(),
142 private final void putQuantityType(Map<Channel, State> targetMap, Channel channel, long value, double factor,
144 // make sure that values are stored as long if no factor is to be applied
145 State val = factor == UNSCALED ? new QuantityType<>(value, unit) : new QuantityType<>(value * factor, unit);
146 targetMap.put(channel, val);
147 logger.debug("Channel {} transformed to QuantityType ({}*{} {}) -> {}", channel.getUID().getId(), value, factor,
151 private final void putOnOffType(Map<Channel, State> targetMap, Channel channel, long value) {
152 State val = ChannelUtil.mapValue(channel, value);
153 targetMap.put(channel, val);
154 logger.debug("Channel {} transformed to OnOffType ({}) -> {}", channel.getUID().getId(), value, val);
157 private final void putDecimalType(Map<Channel, State> targetMap, Channel channel, long value, double factor) {
158 // make sure that values are stored as long if no factor is to be applied
159 State val = factor == UNSCALED ? new DecimalType(value) : new DecimalType(value * factor);
160 targetMap.put(channel, val);
161 logger.debug("Channel {} transformed to DecimalType ({}*{}) -> {}", channel.getUID().getId(), value, factor,