]> git.basschouten.com Git - openhab-addons.git/blob
cd2d6d898bc4885831099dc523b4c18cb7c8c96c
[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 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 {@code QuantityType<Power>} and puts it into the targetMap. If no value or unit is
124      * provided, 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 unitAsString 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 {@code QuantityType<Energy>} and puts it into the targetMap. If no value or unit is
141      * provided 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 unitAsString 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 {@code QuantityType<Energy>} and puts it into the targetMap. If no value or unit is
158      * provided, 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 {@code QuantityType<Energy>} and puts it into the targetMap. If multiple meter value
170      * are 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             Double innerValue = value.value;
182             if (innerValue != null) {
183                 sum += innerValue;
184             }
185         }
186         putEnergyType(targetMap, channel, sum, unit);
187     }
188
189     /**
190      * put value as StringType into targetMap.
191      *
192      * @param targetMap result will be put into this map
193      * @param channel channel to assign the value
194      * @param value the value
195      */
196     protected final void putStringType(Map<Channel, State> targetMap, @Nullable Channel channel,
197             @Nullable String value) {
198         if (channel != null) {
199             State result = UnDefType.UNDEF;
200
201             if (value != null) {
202                 result = new StringType(value);
203                 logger.debug("Channel {} transformed to StringType ({}) -> {}", channel.getUID().getId(), value,
204                         result);
205
206             } else {
207                 logger.debug("Channel {}: no value provided.", channel);
208             }
209             targetMap.put(channel, result);
210         }
211     }
212
213     /**
214      * put value as PercentType into targetMap.
215      *
216      * @param targetMap result will be put into this map
217      * @param channel channel to assign the value
218      * @param value the value to convert
219      * @param factor to be applied (usually 1 or 100)
220      */
221     protected final void putPercentType(Map<Channel, State> targetMap, @Nullable Channel channel,
222             @Nullable Double value, int factor) {
223         if (channel != null) {
224             State result = UnDefType.UNDEF;
225
226             if (value != null) {
227                 result = new QuantityType<>(value * factor, Units.PERCENT);
228             } else {
229                 logger.debug("Channel {}: no value provided.", channel.getUID().getAsString());
230             }
231             targetMap.put(channel, result);
232         }
233     }
234
235     /**
236      * put value as PercentType into targetMap.
237      *
238      * @param targetMap result will be put into this map
239      * @param channel channel to assign the value
240      * @param value the value to convert
241      */
242     protected final void putPercentType(Map<Channel, State> targetMap, @Nullable Channel channel,
243             @Nullable Double value) {
244         putPercentType(targetMap, channel, value, 1);
245     }
246
247     /**
248      * put value as PercentType into targetMap.
249      *
250      * @param targetMap result will be put into this map
251      * @param channel channel to assign the value
252      * @param value the value to convert
253      */
254     protected final void putPercentType(Map<Channel, State> targetMap, @Nullable Channel channel,
255             ValueAndPercent value) {
256         putPercentType(targetMap, channel, value.percentage, 100);
257     }
258
259     /**
260      * calculates percentage and puts it into the targetmap
261      *
262      * @param targetMap result will be put into this map
263      * @param channel channel to assign the value
264      * @param dividendAsState
265      * @param divisorAsState
266      */
267     protected final void putPercentType(Map<Channel, State> targetMap, @Nullable Channel channel,
268             @Nullable State dividendAsState, @Nullable State divisorAsState) {
269         Double percent = null;
270
271         if (dividendAsState != null && divisorAsState != null) {
272             DecimalType dividendAsDecimalType = dividendAsState.as(DecimalType.class);
273             DecimalType divisorAsDecimalType = divisorAsState.as(DecimalType.class);
274
275             if (dividendAsDecimalType != null && divisorAsDecimalType != null) {
276                 double dividend = dividendAsDecimalType.doubleValue();
277                 double divisor = divisorAsDecimalType.doubleValue();
278                 if (dividend >= 0.0 && divisor > 0.0) {
279                     percent = dividend / divisor * 100;
280                 }
281             }
282         }
283
284         putPercentType(targetMap, channel, percent);
285     }
286
287     /**
288      * converts the aggregate period to the correpsonding channel group.
289      *
290      * @param period
291      * @return
292      */
293     protected String convertPeriodToGroup(AggregatePeriod period) {
294         String group = "undefined";
295         switch (period) {
296             case DAY:
297                 group = CHANNEL_GROUP_AGGREGATE_DAY;
298                 break;
299             case WEEK:
300                 group = CHANNEL_GROUP_AGGREGATE_WEEK;
301                 break;
302             case MONTH:
303                 group = CHANNEL_GROUP_AGGREGATE_MONTH;
304                 break;
305             case YEAR:
306                 group = CHANNEL_GROUP_AGGREGATE_YEAR;
307                 break;
308         }
309         return group;
310     }
311 }