2 * Copyright (c) 2010-2022 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.solaredge.internal.model;
15 import static org.openhab.binding.solaredge.internal.SolarEdgeBindingConstants.*;
19 import javax.measure.Quantity;
20 import javax.measure.Unit;
21 import javax.measure.quantity.Energy;
22 import javax.measure.quantity.Power;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.openhab.binding.solaredge.internal.model.AggregateDataResponsePrivateApi.Value;
27 import org.openhab.binding.solaredge.internal.model.AggregateDataResponsePrivateApi.ValueAndPercent;
28 import org.openhab.binding.solaredge.internal.model.AggregateDataResponsePublicApi.MeterTelemetry;
29 import org.openhab.core.library.types.DecimalType;
30 import org.openhab.core.library.types.QuantityType;
31 import org.openhab.core.library.types.StringType;
32 import org.openhab.core.library.unit.MetricPrefix;
33 import org.openhab.core.library.unit.Units;
34 import org.openhab.core.thing.Channel;
35 import org.openhab.core.types.State;
36 import org.openhab.core.types.UnDefType;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
41 * common interface for all data response classes
43 * @author Alexander Friese - initial contribution
46 abstract class AbstractDataResponseTransformer {
47 static final String UNIT_WH = "Wh";
48 static final String UNIT_KWH = "kWh";
49 static final String UNIT_MWH = "MWh";
50 static final String UNIT_W = "W";
51 static final String UNIT_KW = "kW";
52 static final String UNIT_MW = "MW";
57 private static final Logger logger = LoggerFactory.getLogger(AbstractDataResponseTransformer.class);
60 * determines the unit, also handles wrong spelling of kWh (which is spelled with capital K by API)
65 private final @Nullable Unit<Energy> determineEnergyUnit(@Nullable String unit) {
67 if (unit.equals(UNIT_WH)) {
68 return Units.WATT_HOUR;
69 } else if (unit.toLowerCase().equals(UNIT_KWH.toLowerCase())) {
70 return MetricPrefix.KILO(Units.WATT_HOUR);
71 } else if (unit.equals(UNIT_MWH)) {
72 return MetricPrefix.MEGA(Units.WATT_HOUR);
75 logger.debug("Could not determine energy unit: '{}'", unit);
80 * determines the unit, also handles wrong spelling of kW (which is spelled with capital K by API)
85 private final @Nullable Unit<Power> determinePowerUnit(@Nullable String unit) {
87 if (unit.equals(UNIT_W)) {
89 } else if (unit.toLowerCase().equals(UNIT_KW.toLowerCase())) {
90 return MetricPrefix.KILO(Units.WATT);
91 } else if (unit.equals(UNIT_MW)) {
92 return MetricPrefix.MEGA(Units.WATT);
95 logger.debug("Could not determine power unit: '{}'", unit);
100 * converts the value to QuantityType and puts it into the targetMap. If no value or unit is provided
101 * UnDefType.UNDEF will be used
103 * @param targetMap result will be put into this map
104 * @param channel channel to assign the value
105 * @param value the value to convert
106 * @param unit the unit to be used
108 private final <T extends Quantity<T>> void putQuantityType(Map<Channel, State> targetMap, Channel channel,
109 @Nullable Double value, @Nullable Unit<T> unit) {
110 State result = UnDefType.UNDEF;
112 if (value != null && unit != null) {
113 result = new QuantityType<>(value, unit);
114 logger.debug("Channel {} transformed to QuantityType ({} {}) -> {}", channel.getUID().getId(), value, unit,
117 logger.debug("Channel {}: no value/unit provided", channel.getUID().getId());
119 targetMap.put(channel, result);
123 * converts the value to QuantityType<Power> and puts it into the targetMap. If no value or unit is provided
124 * UnDefType.UNDEF will be used
126 * @param targetMap result will be put into this map
127 * @param channel channel to assign the value
128 * @param value the value to convert
129 * @param unit as string
131 protected final void putPowerType(Map<Channel, State> targetMap, @Nullable Channel channel, @Nullable Double value,
132 @Nullable String unitAsString) {
133 if (channel != null) {
134 Unit<Power> unit = determinePowerUnit(unitAsString);
135 putQuantityType(targetMap, channel, value, unit);
140 * converts the value to QuantityType<Energy> and puts it into the targetMap. If no value or unit is provided
141 * UnDefType.UNDEF will be used
143 * @param targetMap result will be put into this map
144 * @param channel channel to assign the value
145 * @param value the value to convert
146 * @param unit as string
148 protected final void putEnergyType(Map<Channel, State> targetMap, @Nullable Channel channel, @Nullable Double value,
149 @Nullable String unitAsString) {
150 if (channel != null) {
151 Unit<Energy> unit = determineEnergyUnit(unitAsString);
152 putQuantityType(targetMap, channel, value, unit);
157 * converts the value to QuantityType<Energy> and puts it into the targetMap. If no value or unit is provided
158 * UnDefType.UNDEF will be used
160 * @param targetMap result will be put into this map
161 * @param channel channel to assign the value
162 * @param value the value to convert
164 protected final void putEnergyType(Map<Channel, State> targetMap, @Nullable Channel channel, Value value) {
165 putEnergyType(targetMap, channel, value.value, value.unit);
169 * converts the meter value to QuantityType<Energy> and puts it into the targetMap. If multiple meter value are
170 * provided a sum will be calculated. If no
171 * unit can be determined UnDefType.UNDEF will be used
173 * @param targetMap result will be put into this map
174 * @param channel channel to assign the value
175 * @param values one or more meter values
177 protected final void putEnergyType(Map<Channel, State> targetMap, @Nullable Channel channel, @Nullable String unit,
178 MeterTelemetry... values) {
180 for (MeterTelemetry value : values) {
181 if (value.value != null) {
185 putEnergyType(targetMap, channel, sum, unit);
189 * put value as StringType into targetMap.
191 * @param targetMap result will be put into this map
192 * @param channel channel to assign the value
193 * @param value the value
195 protected final void putStringType(Map<Channel, State> targetMap, @Nullable Channel channel,
196 @Nullable String value) {
197 if (channel != null) {
198 State result = UnDefType.UNDEF;
201 result = new StringType(value);
202 logger.debug("Channel {} transformed to StringType ({}) -> {}", channel.getUID().getId(), value,
206 logger.debug("Channel {}: no value provided.", channel);
208 targetMap.put(channel, result);
213 * put value as PercentType into targetMap.
215 * @param targetMap result will be put into this map
216 * @param channel channel to assign the value
217 * @param value the value to convert
218 * @param factor to be applied (usually 1 or 100)
220 protected final void putPercentType(Map<Channel, State> targetMap, @Nullable Channel channel,
221 @Nullable Double value, int factor) {
222 if (channel != null) {
223 State result = UnDefType.UNDEF;
226 result = new QuantityType<>(value * factor, Units.PERCENT);
228 logger.debug("Channel {}: no value provided.", channel.getUID().getAsString());
230 targetMap.put(channel, result);
235 * put value as PercentType into targetMap.
237 * @param targetMap result will be put into this map
238 * @param channel channel to assign the value
239 * @param value the value to convert
241 protected final void putPercentType(Map<Channel, State> targetMap, @Nullable Channel channel,
242 @Nullable Double value) {
243 putPercentType(targetMap, channel, value, 1);
247 * put value as PercentType into targetMap.
249 * @param targetMap result will be put into this map
250 * @param channel channel to assign the value
251 * @param value the value to convert
253 protected final void putPercentType(Map<Channel, State> targetMap, @Nullable Channel channel,
254 ValueAndPercent value) {
255 putPercentType(targetMap, channel, value.percentage, 100);
259 * calculates percentage and puts it into the targetmap
261 * @param targetMap result will be put into this map
262 * @param channel channel to assign the value
263 * @param dividendAsState
264 * @param divisorAsState
266 protected final void putPercentType(Map<Channel, State> targetMap, @Nullable Channel channel,
267 @Nullable State dividendAsState, @Nullable State divisorAsState) {
268 Double percent = null;
270 if (dividendAsState != null && divisorAsState != null) {
271 DecimalType dividendAsDecimalType = dividendAsState.as(DecimalType.class);
272 DecimalType divisorAsDecimalType = divisorAsState.as(DecimalType.class);
274 if (dividendAsDecimalType != null && divisorAsDecimalType != null) {
275 double dividend = dividendAsDecimalType.doubleValue();
276 double divisor = divisorAsDecimalType.doubleValue();
277 if (dividend >= 0.0 && divisor > 0.0) {
278 percent = dividend / divisor * 100;
283 putPercentType(targetMap, channel, percent);
287 * converts the aggregate period to the correpsonding channel group.
292 protected String convertPeriodToGroup(AggregatePeriod period) {
293 String group = "undefined";
296 group = CHANNEL_GROUP_AGGREGATE_DAY;
299 group = CHANNEL_GROUP_AGGREGATE_WEEK;
302 group = CHANNEL_GROUP_AGGREGATE_MONTH;
305 group = CHANNEL_GROUP_AGGREGATE_YEAR;