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.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.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
37 * transforms the http response into the openhab datamodel (instances of State)
39 * @author Alexander Friese - initial contribution
42 public class DataResponseTransformer {
43 private final Logger logger = LoggerFactory.getLogger(DataResponseTransformer.class);
45 private static final double UNSCALED = 1;
46 private static final double DIV_10 = 0.1;
47 private static final double DIV_100 = 0.01;
49 private final ChannelProvider channelProvider;
51 public DataResponseTransformer(ChannelProvider channelProvider) {
52 this.channelProvider = channelProvider;
55 public Map<Channel, State> transform(DataResponse response) {
56 Map<String, Long> source = response.getValues();
57 Map<Channel, State> result = new HashMap<>(source.size());
59 for (String channelId : source.keySet()) {
60 Long value = source.get(channelId);
62 Channel channel = channelProvider.getSpecificChannel(channelId);
63 if (channel == null) {
64 // This should not happen but we want to get informed about it
65 logger.warn("Channel not found: {}", channelId);
67 ChannelTypeUID typeUID = channel.getChannelTypeUID();
68 String type = typeUID == null ? "null" : typeUID.getId();
71 case CHANNEL_TYPE_TEMPERATURE:
72 case CHANNEL_TYPE_START_COOLING_RW:
73 putQuantityType(result, channel, value, DIV_10, SIUnits.CELSIUS);
75 case CHANNEL_TYPE_PRESSURE:
76 putQuantityType(result, channel, value, DIV_10, Units.BAR);
78 case CHANNEL_TYPE_ENERGY:
79 putQuantityType(result, channel, value, DIV_10, MetricPrefix.KILO(Units.WATT_HOUR));
81 case CHANNEL_TYPE_POWER:
82 putQuantityType(result, channel, value, DIV_100, MetricPrefix.KILO(Units.WATT));
84 case CHANNEL_TYPE_SWITCH_RW:
85 case CHANNEL_TYPE_SWITCH:
86 putOnOffType(result, channel, value);
88 case CHANNEL_TYPE_ELECTRIC_CURRENT:
89 putQuantityType(result, channel, value, DIV_10, Units.AMPERE);
91 case CHANNEL_TYPE_TIME_UNSCALED:
92 putQuantityType(result, channel, value, UNSCALED, Units.HOUR);
94 case CHANNEL_TYPE_TIME_SCALE10:
95 putQuantityType(result, channel, value, DIV_10, Units.HOUR);
97 case CHANNEL_TYPE_FREQUENCY_UNSCALED:
98 putQuantityType(result, channel, value, UNSCALED, Units.HERTZ);
100 case CHANNEL_TYPE_FREQUENCY_SCALE10:
101 putQuantityType(result, channel, value, DIV_10, Units.HERTZ);
103 case CHANNEL_TYPE_FLOW:
104 putQuantityType(result, channel, value, DIV_10, Units.LITRE.divide(Units.MINUTE));
106 case CHANNEL_TYPE_SPEED:
107 putQuantityType(result, channel, value, UNSCALED, Units.PERCENT);
109 case CHANNEL_TYPE_NUMBER_SCALE100:
110 putDecimalType(result, channel, value, DIV_100);
112 case CHANNEL_TYPE_NUMBER_SCALE10:
113 case CHANNEL_TYPE_DEGREE_MINUTES_RW:
114 case CHANNEL_TYPE_STOP_HEATING_RW:
115 case CHANNEL_TYPE_STOP_ADD_HEATING_RW:
116 case CHANNEL_TYPE_ROOM_SENSOR_FACTOR_RW:
117 putDecimalType(result, channel, value, DIV_10);
119 case CHANNEL_TYPE_NUMBER_UNSCALED:
120 case CHANNEL_TYPE_DEFROSTING_STATE:
121 case CHANNEL_TYPE_HPAC_STATE:
122 case CHANNEL_TYPE_HW_LUX_RW:
123 case CHANNEL_TYPE_HW_MODE_RW:
124 case CHANNEL_TYPE_FAN_SPEED_RW:
125 case CHANNEL_TYPE_FILTER_TIME_RW:
126 case CHANNEL_TYPE_HEAT_OFFSET_RW:
127 putDecimalType(result, channel, value, UNSCALED);
130 logger.warn("could not handle unknown type {}, channel {}, value {}", type, channel.getUID(),
138 private final void putQuantityType(Map<Channel, State> targetMap, Channel channel, long value, double factor,
140 // make sure that values are stored as long if no factor is to be applied
141 State val = factor == UNSCALED ? new QuantityType<>(value, unit) : new QuantityType<>(value * factor, unit);
142 targetMap.put(channel, val);
143 logger.debug("Channel {} transformed to QuantityType ({}*{} {}) -> {}", channel.getUID().getId(), value, factor,
147 private final void putOnOffType(Map<Channel, State> targetMap, Channel channel, long value) {
148 State val = ChannelUtil.mapValue(channel, value);
149 targetMap.put(channel, val);
150 logger.debug("Channel {} transformed to OnOffType ({}) -> {}", channel.getUID().getId(), value, val);
153 private final void putDecimalType(Map<Channel, State> targetMap, Channel channel, long value, double factor) {
154 // make sure that values are stored as long if no factor is to be applied
155 State val = factor == UNSCALED ? new DecimalType(value) : new DecimalType(value * factor);
156 targetMap.put(channel, val);
157 logger.debug("Channel {} transformed to DecimalType ({}*{}) -> {}", channel.getUID().getId(), value, factor,