]> git.basschouten.com Git - openhab-addons.git/blob
8fef7cff87da458363b801518efcae119d1e4a7e
[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.hue.internal.dto.clip2.helper;
14
15 import java.math.BigDecimal;
16 import java.util.List;
17 import java.util.Objects;
18
19 import javax.measure.Unit;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.hue.internal.dto.clip2.Alerts;
24 import org.openhab.binding.hue.internal.dto.clip2.ColorTemperature;
25 import org.openhab.binding.hue.internal.dto.clip2.ColorXy;
26 import org.openhab.binding.hue.internal.dto.clip2.Dimming;
27 import org.openhab.binding.hue.internal.dto.clip2.Effects;
28 import org.openhab.binding.hue.internal.dto.clip2.MetaData;
29 import org.openhab.binding.hue.internal.dto.clip2.MirekSchema;
30 import org.openhab.binding.hue.internal.dto.clip2.OnState;
31 import org.openhab.binding.hue.internal.dto.clip2.Resource;
32 import org.openhab.binding.hue.internal.dto.clip2.enums.ActionType;
33 import org.openhab.binding.hue.internal.dto.clip2.enums.EffectType;
34 import org.openhab.core.library.types.DecimalType;
35 import org.openhab.core.library.types.HSBType;
36 import org.openhab.core.library.types.PercentType;
37 import org.openhab.core.library.types.QuantityType;
38 import org.openhab.core.library.types.StringType;
39 import org.openhab.core.library.unit.Units;
40 import org.openhab.core.types.Command;
41 import org.openhab.core.util.ColorUtil;
42 import org.openhab.core.util.ColorUtil.Gamut;
43
44 /**
45  * Advanced setter methods for fields in the Resource class for special cases where setting the new value in the target
46  * resource depends on logic using the values of other fields in a another source Resource.
47  *
48  * @author Andrew Fiddian-Green - Initial contribution
49  */
50 @NonNullByDefault
51 public class Setters {
52
53     /**
54      * Setter for Alert field:
55      * Use the given command value to set the target resource DTO value based on the attributes of the source resource
56      * (if any).
57      *
58      * @param target the target resource.
59      * @param command the new state command should be a StringType.
60      * @param source another resource containing the allowed alert action values.
61      *
62      * @return the target resource.
63      */
64     public static Resource setAlert(Resource target, Command command, @Nullable Resource source) {
65         if ((command instanceof StringType) && Objects.nonNull(source)) {
66             Alerts otherAlert = source.getAlerts();
67             if (Objects.nonNull(otherAlert)) {
68                 ActionType actionType = ActionType.of(((StringType) command).toString());
69                 if (otherAlert.getActionValues().contains(actionType)) {
70                     target.setAlerts(new Alerts().setAction(actionType));
71                 }
72             }
73         }
74         return target;
75     }
76
77     /**
78      * Setter for Color Temperature field:
79      * Use the given command value to set the target resource DTO value based on the attributes of the source resource
80      * (if any).
81      *
82      * @param target the target resource.
83      * @param command the new state command should be a QuantityType<Temperature> (but it can also handle DecimalType).
84      * @param source another resource containing the MirekSchema.
85      *
86      * @return the target resource.
87      */
88     public static Resource setColorTemperatureAbsolute(Resource target, Command command, @Nullable Resource source) {
89         QuantityType<?> mirek;
90         if (command instanceof QuantityType<?>) {
91             QuantityType<?> quantity = (QuantityType<?>) command;
92             Unit<?> unit = quantity.getUnit();
93             if (Units.KELVIN.equals(unit)) {
94                 mirek = quantity.toInvertibleUnit(Units.MIRED);
95             } else if (Units.MIRED.equals(unit)) {
96                 mirek = quantity;
97             } else {
98                 QuantityType<?> kelvin = quantity.toInvertibleUnit(Units.KELVIN);
99                 mirek = Objects.nonNull(kelvin) ? kelvin.toInvertibleUnit(Units.MIRED) : null;
100             }
101         } else if (command instanceof DecimalType) {
102             mirek = QuantityType.valueOf(((DecimalType) command).doubleValue(), Units.KELVIN)
103                     .toInvertibleUnit(Units.MIRED);
104         } else {
105             mirek = null;
106         }
107         if (Objects.nonNull(mirek)) {
108             MirekSchema schema = target.getMirekSchema();
109             schema = Objects.nonNull(schema) ? schema : Objects.nonNull(source) ? source.getMirekSchema() : null;
110             schema = Objects.nonNull(schema) ? schema : MirekSchema.DEFAULT_SCHEMA;
111             ColorTemperature colorTemperature = target.getColorTemperature();
112             colorTemperature = Objects.nonNull(colorTemperature) ? colorTemperature : new ColorTemperature();
113             double min = schema.getMirekMinimum();
114             double max = schema.getMirekMaximum();
115             double val = Math.max(min, Math.min(max, mirek.doubleValue()));
116             target.setColorTemperature(colorTemperature.setMirek(val));
117         }
118         return target;
119     }
120
121     /**
122      * Setter for Color Temperature field:
123      * Use the given command value to set the target resource DTO value based on the attributes of the source resource
124      * (if any).
125      *
126      * @param target the target resource.
127      * @param command the new state command should be a PercentType.
128      * @param source another resource containing the MirekSchema.
129      *
130      * @return the target resource.
131      */
132     public static Resource setColorTemperaturePercent(Resource target, Command command, @Nullable Resource source) {
133         if (command instanceof PercentType) {
134             MirekSchema schema = target.getMirekSchema();
135             schema = Objects.nonNull(schema) ? schema : Objects.nonNull(source) ? source.getMirekSchema() : null;
136             schema = Objects.nonNull(schema) ? schema : MirekSchema.DEFAULT_SCHEMA;
137             ColorTemperature colorTemperature = target.getColorTemperature();
138             colorTemperature = Objects.nonNull(colorTemperature) ? colorTemperature : new ColorTemperature();
139             double min = schema.getMirekMinimum();
140             double max = schema.getMirekMaximum();
141             double val = min + ((max - min) * ((PercentType) command).doubleValue() / 100f);
142             target.setColorTemperature(colorTemperature.setMirek(val));
143         }
144         return target;
145     }
146
147     /**
148      * Setter for Color Xy field:
149      * Use the given command value to set the target resource DTO value based on the attributes of the source resource
150      * (if any). Use the HS parts of the HSB value to set the value of the 'ColorXy' JSON element, and ignore the 'B'
151      * part.
152      *
153      * @param target the target resource.
154      * @param command the new state command should be an HSBType with the new color XY value.
155      * @param source another resource containing the color Gamut.
156      *
157      * @return the target resource.
158      */
159     public static Resource setColorXy(Resource target, Command command, @Nullable Resource source) {
160         if (command instanceof HSBType) {
161             Gamut gamut = target.getGamut();
162             gamut = Objects.nonNull(gamut) ? gamut : Objects.nonNull(source) ? source.getGamut() : null;
163             gamut = Objects.nonNull(gamut) ? gamut : ColorUtil.DEFAULT_GAMUT;
164             HSBType hsb = (HSBType) command;
165             ColorXy color = target.getColorXy();
166             target.setColorXy((Objects.nonNull(color) ? color : new ColorXy()).setXY(ColorUtil.hsbToXY(hsb, gamut)));
167         }
168         return target;
169     }
170
171     /**
172      * Setter for Dimming field:
173      * Use the given command value to set the target resource DTO value based on the attributes of the source resource
174      * (if any).
175      *
176      * @param target the target resource.
177      * @param command the new state command should be a PercentType with the new dimming parameter.
178      * @param source another resource containing the minimum dimming level.
179      *
180      * @return the target resource.
181      */
182     public static Resource setDimming(Resource target, Command command, @Nullable Resource source) {
183         if (command instanceof PercentType) {
184             Double min = target.getMinimumDimmingLevel();
185             min = Objects.nonNull(min) ? min : Objects.nonNull(source) ? source.getMinimumDimmingLevel() : null;
186             min = Objects.nonNull(min) ? min : Dimming.DEFAULT_MINIMUM_DIMMIMG_LEVEL;
187             PercentType brightness = (PercentType) command;
188             if (brightness.doubleValue() < min.doubleValue()) {
189                 brightness = new PercentType(new BigDecimal(min, Resource.PERCENT_MATH_CONTEXT));
190             }
191             Dimming dimming = target.getDimming();
192             dimming = Objects.nonNull(dimming) ? dimming : new Dimming();
193             dimming.setBrightness(brightness.doubleValue());
194             target.setDimming(dimming);
195         }
196         return target;
197     }
198
199     /**
200      * Setter for Effect field:
201      * Use the given command value to set the target resource DTO value based on the attributes of the source resource
202      * (if any).
203      *
204      * @param target the target resource.
205      * @param command the new state command should be a StringType.
206      * @param source another resource containing the allowed effect action values.
207      *
208      * @return the target resource.
209      */
210     public static Resource setEffect(Resource target, Command command, @Nullable Resource source) {
211         if ((command instanceof StringType) && Objects.nonNull(source)) {
212             Effects otherEffects = source.getEffects();
213             if (Objects.nonNull(otherEffects)) {
214                 EffectType effectType = EffectType.of(((StringType) command).toString());
215                 if (otherEffects.allows(effectType)) {
216                     target.setEffects(new Effects().setEffect(effectType));
217                 }
218             }
219         }
220         return target;
221     }
222
223     /**
224      * Setter to copy persisted fields from the source Resource into the target Resource. If the field in the target is
225      * null and the same field in the source is not null, then the value from the source is copied to the target. This
226      * method allows 'hasSparseData' resources to expand themselves to include necessary fields taken over from a
227      * previously cached full data resource.
228      *
229      * @param target the target resource.
230      * @param source another resource containing the values to be taken over.
231      *
232      * @return the target resource.
233      */
234     public static Resource setResource(Resource target, Resource source) {
235         // on
236         OnState targetOnOff = target.getOnState();
237         OnState sourceOnOff = source.getOnState();
238         if (Objects.isNull(targetOnOff) && Objects.nonNull(sourceOnOff)) {
239             target.setOnState(sourceOnOff);
240         }
241         // dimming
242         Dimming targetDimming = target.getDimming();
243         Dimming sourceDimming = source.getDimming();
244         if (Objects.isNull(targetDimming) && Objects.nonNull(sourceDimming)) {
245             target.setDimming(sourceDimming);
246             targetDimming = target.getDimming();
247         }
248         // minimum dimming level
249         Double targetMinDimmingLevel = Objects.nonNull(targetDimming) ? targetDimming.getMinimumDimmingLevel() : null;
250         Double sourceMinDimmingLevel = Objects.nonNull(sourceDimming) ? sourceDimming.getMinimumDimmingLevel() : null;
251         if (Objects.isNull(targetMinDimmingLevel) && Objects.nonNull(sourceMinDimmingLevel)) {
252             targetDimming = Objects.nonNull(targetDimming) ? targetDimming : new Dimming();
253             targetDimming.setMinimumDimmingLevel(sourceMinDimmingLevel);
254         }
255         // color
256         ColorXy targetColor = target.getColorXy();
257         ColorXy sourceColor = source.getColorXy();
258         if (Objects.isNull(targetColor) && Objects.nonNull(sourceColor)) {
259             target.setColorXy(sourceColor);
260             targetColor = target.getColorXy();
261         }
262         // color gamut
263         Gamut targetGamut = Objects.nonNull(targetColor) ? targetColor.getGamut() : null;
264         Gamut sourceGamut = Objects.nonNull(sourceColor) ? sourceColor.getGamut() : null;
265         if (Objects.isNull(targetGamut) && Objects.nonNull(sourceGamut)) {
266             targetColor = Objects.nonNull(targetColor) ? targetColor : new ColorXy();
267             targetColor.setGamut(sourceGamut);
268         }
269         // color temperature
270         ColorTemperature targetColorTemp = target.getColorTemperature();
271         ColorTemperature sourceColorTemp = source.getColorTemperature();
272         if (Objects.isNull(targetColorTemp) && Objects.nonNull(sourceColorTemp)) {
273             target.setColorTemperature(sourceColorTemp);
274             targetColorTemp = target.getColorTemperature();
275         }
276         // mirek schema
277         MirekSchema targetMirekSchema = Objects.nonNull(targetColorTemp) ? targetColorTemp.getMirekSchema() : null;
278         MirekSchema sourceMirekSchema = Objects.nonNull(sourceColorTemp) ? sourceColorTemp.getMirekSchema() : null;
279         if (Objects.isNull(targetMirekSchema) && Objects.nonNull(sourceMirekSchema)) {
280             targetColorTemp = Objects.nonNull(targetColorTemp) ? targetColorTemp : new ColorTemperature();
281             targetColorTemp.setMirekSchema(sourceMirekSchema);
282         }
283         // metadata
284         MetaData targetMetaData = target.getMetaData();
285         MetaData sourceMetaData = source.getMetaData();
286         if (Objects.isNull(targetMetaData) && Objects.nonNull(sourceMetaData)) {
287             target.setMetadata(sourceMetaData);
288         }
289         // alerts
290         Alerts targetAlerts = target.getAlerts();
291         Alerts sourceAlerts = source.getAlerts();
292         if (Objects.isNull(targetAlerts) && Objects.nonNull(sourceAlerts)) {
293             target.setAlerts(sourceAlerts);
294         }
295         // effects
296         Effects targetEffects = target.getEffects();
297         Effects sourceEffects = source.getEffects();
298         if (Objects.isNull(targetEffects) && Objects.nonNull(sourceEffects)) {
299             targetEffects = sourceEffects;
300             target.setEffects(sourceEffects);
301             targetEffects = target.getEffects();
302         }
303         // effects values
304         List<String> targetStatusValues = Objects.nonNull(targetEffects) ? targetEffects.getStatusValues() : null;
305         List<String> sourceStatusValues = Objects.nonNull(sourceEffects) ? sourceEffects.getStatusValues() : null;
306         if (Objects.isNull(targetStatusValues) && Objects.nonNull(sourceStatusValues)) {
307             targetEffects = Objects.nonNull(targetEffects) ? targetEffects : new Effects();
308             targetEffects.setStatusValues(sourceStatusValues);
309         }
310         return target;
311     }
312 }