]> git.basschouten.com Git - openhab-addons.git/blob
4931c13772828b5be1a19518a1ad7ff3116fd825
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.solaredge.internal.model;
14
15 import static org.openhab.binding.solaredge.internal.SolarEdgeBindingConstants.*;
16
17 import java.util.Map;
18
19 import javax.measure.Quantity;
20 import javax.measure.Unit;
21 import javax.measure.quantity.Energy;
22 import javax.measure.quantity.Power;
23
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;
39
40 /**
41  * common interface for all data response classes
42  *
43  * @author Alexander Friese - initial contribution
44  */
45 @NonNullByDefault
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";
53
54     /**
55      * logger
56      */
57     private static final Logger logger = LoggerFactory.getLogger(AbstractDataResponseTransformer.class);
58
59     /**
60      * determines the unit, also handles wrong spelling of kWh (which is spelled with capital K by API)
61      *
62      * @param unit
63      * @return
64      */
65     private final @Nullable Unit<Energy> determineEnergyUnit(@Nullable String unit) {
66         if (unit != null) {
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);
73             }
74         }
75         logger.debug("Could not determine energy unit: '{}'", unit);
76         return null;
77     }
78
79     /**
80      * determines the unit, also handles wrong spelling of kW (which is spelled with capital K by API)
81      *
82      * @param unit
83      * @return
84      */
85     private final @Nullable Unit<Power> determinePowerUnit(@Nullable String unit) {
86         if (unit != null) {
87             if (unit.equals(UNIT_W)) {
88                 return Units.WATT;
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);
93             }
94         }
95         logger.debug("Could not determine power unit: '{}'", unit);
96         return null;
97     }
98
99     /**
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
102      *
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
107      */
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;
111
112         if (value != null && unit != null) {
113             result = new QuantityType<>(value, unit);
114             logger.debug("Channel {} transformed to QuantityType ({} {}) -> {}", channel.getUID().getId(), value, unit,
115                     result);
116         } else {
117             logger.debug("Channel {}: no value/unit provided", channel.getUID().getId());
118         }
119         targetMap.put(channel, result);
120     }
121
122     /**
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
125      *
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
130      */
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);
136         }
137     }
138
139     /**
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
142      *
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
147      */
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);
153         }
154     }
155
156     /**
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
159      *
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
163      */
164     protected final void putEnergyType(Map<Channel, State> targetMap, @Nullable Channel channel, Value value) {
165         putEnergyType(targetMap, channel, value.value, value.unit);
166     }
167
168     /**
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
172      *
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
176      */
177     protected final void putEnergyType(Map<Channel, State> targetMap, @Nullable Channel channel, @Nullable String unit,
178             MeterTelemetry... values) {
179         double sum = 0.0;
180         for (MeterTelemetry value : values) {
181             if (value.value != null) {
182                 sum += value.value;
183             }
184         }
185         putEnergyType(targetMap, channel, sum, unit);
186     }
187
188     /**
189      * put value as StringType into targetMap.
190      *
191      * @param targetMap result will be put into this map
192      * @param channel channel to assign the value
193      * @param value the value
194      */
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;
199
200             if (value != null) {
201                 result = new StringType(value);
202                 logger.debug("Channel {} transformed to StringType ({}) -> {}", channel.getUID().getId(), value,
203                         result);
204
205             } else {
206                 logger.debug("Channel {}: no value provided.", channel);
207             }
208             targetMap.put(channel, result);
209         }
210     }
211
212     /**
213      * put value as PercentType into targetMap.
214      *
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)
219      */
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;
224
225             if (value != null) {
226                 result = new QuantityType<>(value * factor, Units.PERCENT);
227             } else {
228                 logger.debug("Channel {}: no value provided.", channel.getUID().getAsString());
229             }
230             targetMap.put(channel, result);
231         }
232     }
233
234     /**
235      * put value as PercentType into targetMap.
236      *
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
240      */
241     protected final void putPercentType(Map<Channel, State> targetMap, @Nullable Channel channel,
242             @Nullable Double value) {
243         putPercentType(targetMap, channel, value, 1);
244     }
245
246     /**
247      * put value as PercentType into targetMap.
248      *
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
252      */
253     protected final void putPercentType(Map<Channel, State> targetMap, @Nullable Channel channel,
254             ValueAndPercent value) {
255         putPercentType(targetMap, channel, value.percentage, 100);
256     }
257
258     /**
259      * calculates percentage and puts it into the targetmap
260      *
261      * @param targetMap result will be put into this map
262      * @param channel channel to assign the value
263      * @param dividendAsState
264      * @param divisorAsState
265      */
266     protected final void putPercentType(Map<Channel, State> targetMap, @Nullable Channel channel,
267             @Nullable State dividendAsState, @Nullable State divisorAsState) {
268         Double percent = null;
269
270         if (dividendAsState != null && divisorAsState != null) {
271             DecimalType dividendAsDecimalType = dividendAsState.as(DecimalType.class);
272             DecimalType divisorAsDecimalType = divisorAsState.as(DecimalType.class);
273
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;
279                 }
280             }
281         }
282
283         putPercentType(targetMap, channel, percent);
284     }
285
286     /**
287      * converts the aggregate period to the correpsonding channel group.
288      *
289      * @param period
290      * @return
291      */
292     protected String convertPeriodToGroup(AggregatePeriod period) {
293         String group = "undefined";
294         switch (period) {
295             case DAY:
296                 group = CHANNEL_GROUP_AGGREGATE_DAY;
297                 break;
298             case WEEK:
299                 group = CHANNEL_GROUP_AGGREGATE_WEEK;
300                 break;
301             case MONTH:
302                 group = CHANNEL_GROUP_AGGREGATE_MONTH;
303                 break;
304             case YEAR:
305                 group = CHANNEL_GROUP_AGGREGATE_YEAR;
306                 break;
307         }
308         return group;
309     }
310 }