]> git.basschouten.com Git - openhab-addons.git/blob
17dc1b6d2b8a627247af0de729d104f8037c0bfe
[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 {@code QuantityType<Temperature>} (but it can also handle
84      *            {@code DecimalType}).
85      * @param source another resource containing the MirekSchema.
86      *
87      * @return the target resource.
88      */
89     public static Resource setColorTemperatureAbsolute(Resource target, Command command, @Nullable Resource source) {
90         QuantityType<?> mirek;
91         if (command instanceof QuantityType<?>) {
92             QuantityType<?> quantity = (QuantityType<?>) command;
93             Unit<?> unit = quantity.getUnit();
94             if (Units.KELVIN.equals(unit)) {
95                 mirek = quantity.toInvertibleUnit(Units.MIRED);
96             } else if (Units.MIRED.equals(unit)) {
97                 mirek = quantity;
98             } else {
99                 QuantityType<?> kelvin = quantity.toInvertibleUnit(Units.KELVIN);
100                 mirek = Objects.nonNull(kelvin) ? kelvin.toInvertibleUnit(Units.MIRED) : null;
101             }
102         } else if (command instanceof DecimalType) {
103             mirek = QuantityType.valueOf(((DecimalType) command).doubleValue(), Units.KELVIN)
104                     .toInvertibleUnit(Units.MIRED);
105         } else {
106             mirek = null;
107         }
108         if (Objects.nonNull(mirek)) {
109             MirekSchema schema = target.getMirekSchema();
110             schema = Objects.nonNull(schema) ? schema : Objects.nonNull(source) ? source.getMirekSchema() : null;
111             schema = Objects.nonNull(schema) ? schema : MirekSchema.DEFAULT_SCHEMA;
112             ColorTemperature colorTemperature = target.getColorTemperature();
113             colorTemperature = Objects.nonNull(colorTemperature) ? colorTemperature : new ColorTemperature();
114             double min = schema.getMirekMinimum();
115             double max = schema.getMirekMaximum();
116             double val = Math.max(min, Math.min(max, mirek.doubleValue()));
117             target.setColorTemperature(colorTemperature.setMirek(val));
118         }
119         return target;
120     }
121
122     /**
123      * Setter for Color Temperature field:
124      * Use the given command value to set the target resource DTO value based on the attributes of the source resource
125      * (if any).
126      *
127      * @param target the target resource.
128      * @param command the new state command should be a PercentType.
129      * @param source another resource containing the MirekSchema.
130      *
131      * @return the target resource.
132      */
133     public static Resource setColorTemperaturePercent(Resource target, Command command, @Nullable Resource source) {
134         if (command instanceof PercentType) {
135             MirekSchema schema = target.getMirekSchema();
136             schema = Objects.nonNull(schema) ? schema : Objects.nonNull(source) ? source.getMirekSchema() : null;
137             schema = Objects.nonNull(schema) ? schema : MirekSchema.DEFAULT_SCHEMA;
138             ColorTemperature colorTemperature = target.getColorTemperature();
139             colorTemperature = Objects.nonNull(colorTemperature) ? colorTemperature : new ColorTemperature();
140             double min = schema.getMirekMinimum();
141             double max = schema.getMirekMaximum();
142             double val = min + ((max - min) * ((PercentType) command).doubleValue() / 100f);
143             target.setColorTemperature(colorTemperature.setMirek(val));
144         }
145         return target;
146     }
147
148     /**
149      * Setter for Color Xy field:
150      * Use the given command value to set the target resource DTO value based on the attributes of the source resource
151      * (if any). Use the HS parts of the HSB value to set the value of the 'ColorXy' JSON element, and ignore the 'B'
152      * part.
153      *
154      * @param target the target resource.
155      * @param command the new state command should be an HSBType with the new color XY value.
156      * @param source another resource containing the color Gamut.
157      *
158      * @return the target resource.
159      */
160     public static Resource setColorXy(Resource target, Command command, @Nullable Resource source) {
161         if (command instanceof HSBType) {
162             Gamut gamut = target.getGamut();
163             gamut = Objects.nonNull(gamut) ? gamut : Objects.nonNull(source) ? source.getGamut() : null;
164             gamut = Objects.nonNull(gamut) ? gamut : ColorUtil.DEFAULT_GAMUT;
165             HSBType hsb = (HSBType) command;
166             ColorXy color = target.getColorXy();
167             target.setColorXy((Objects.nonNull(color) ? color : new ColorXy()).setXY(ColorUtil.hsbToXY(hsb, gamut)));
168         }
169         return target;
170     }
171
172     /**
173      * Setter for Dimming field:
174      * Use the given command value to set the target resource DTO value based on the attributes of the source resource
175      * (if any).
176      *
177      * @param target the target resource.
178      * @param command the new state command should be a PercentType with the new dimming parameter.
179      * @param source another resource containing the minimum dimming level.
180      *
181      * @return the target resource.
182      */
183     public static Resource setDimming(Resource target, Command command, @Nullable Resource source) {
184         if (command instanceof PercentType) {
185             Double min = target.getMinimumDimmingLevel();
186             min = Objects.nonNull(min) ? min : Objects.nonNull(source) ? source.getMinimumDimmingLevel() : null;
187             min = Objects.nonNull(min) ? min : Dimming.DEFAULT_MINIMUM_DIMMIMG_LEVEL;
188             PercentType brightness = (PercentType) command;
189             if (brightness.doubleValue() < min.doubleValue()) {
190                 brightness = new PercentType(new BigDecimal(min, Resource.PERCENT_MATH_CONTEXT));
191             }
192             Dimming dimming = target.getDimming();
193             dimming = Objects.nonNull(dimming) ? dimming : new Dimming();
194             dimming.setBrightness(brightness.doubleValue());
195             target.setDimming(dimming);
196         }
197         return target;
198     }
199
200     /**
201      * Setter for Effect field:
202      * Use the given command value to set the target resource DTO value based on the attributes of the source resource
203      * (if any).
204      *
205      * @param target the target resource.
206      * @param command the new state command should be a StringType.
207      * @param source another resource containing the allowed effect action values.
208      *
209      * @return the target resource.
210      */
211     public static Resource setEffect(Resource target, Command command, @Nullable Resource source) {
212         if ((command instanceof StringType) && Objects.nonNull(source)) {
213             Effects otherEffects = source.getEffects();
214             if (Objects.nonNull(otherEffects)) {
215                 EffectType effectType = EffectType.of(((StringType) command).toString());
216                 if (otherEffects.allows(effectType)) {
217                     target.setEffects(new Effects().setEffect(effectType));
218                 }
219             }
220         }
221         return target;
222     }
223
224     /**
225      * Setter to copy persisted fields from the source Resource into the target Resource. If the field in the target is
226      * null and the same field in the source is not null, then the value from the source is copied to the target. This
227      * method allows 'hasSparseData' resources to expand themselves to include necessary fields taken over from a
228      * previously cached full data resource.
229      *
230      * @param target the target resource.
231      * @param source another resource containing the values to be taken over.
232      *
233      * @return the target resource.
234      */
235     public static Resource setResource(Resource target, Resource source) {
236         // on
237         OnState targetOnOff = target.getOnState();
238         OnState sourceOnOff = source.getOnState();
239         if (Objects.isNull(targetOnOff) && Objects.nonNull(sourceOnOff)) {
240             target.setOnState(sourceOnOff);
241         }
242         // dimming
243         Dimming targetDimming = target.getDimming();
244         Dimming sourceDimming = source.getDimming();
245         if (Objects.isNull(targetDimming) && Objects.nonNull(sourceDimming)) {
246             target.setDimming(sourceDimming);
247             targetDimming = target.getDimming();
248         }
249         // minimum dimming level
250         Double targetMinDimmingLevel = Objects.nonNull(targetDimming) ? targetDimming.getMinimumDimmingLevel() : null;
251         Double sourceMinDimmingLevel = Objects.nonNull(sourceDimming) ? sourceDimming.getMinimumDimmingLevel() : null;
252         if (Objects.isNull(targetMinDimmingLevel) && Objects.nonNull(sourceMinDimmingLevel)) {
253             targetDimming = Objects.nonNull(targetDimming) ? targetDimming : new Dimming();
254             targetDimming.setMinimumDimmingLevel(sourceMinDimmingLevel);
255         }
256         // color
257         ColorXy targetColor = target.getColorXy();
258         ColorXy sourceColor = source.getColorXy();
259         if (Objects.isNull(targetColor) && Objects.nonNull(sourceColor)) {
260             target.setColorXy(sourceColor);
261             targetColor = target.getColorXy();
262         }
263         // color gamut
264         Gamut targetGamut = Objects.nonNull(targetColor) ? targetColor.getGamut() : null;
265         Gamut sourceGamut = Objects.nonNull(sourceColor) ? sourceColor.getGamut() : null;
266         if (Objects.isNull(targetGamut) && Objects.nonNull(sourceGamut)) {
267             targetColor = Objects.nonNull(targetColor) ? targetColor : new ColorXy();
268             targetColor.setGamut(sourceGamut);
269         }
270         // color temperature
271         ColorTemperature targetColorTemp = target.getColorTemperature();
272         ColorTemperature sourceColorTemp = source.getColorTemperature();
273         if (Objects.isNull(targetColorTemp) && Objects.nonNull(sourceColorTemp)) {
274             target.setColorTemperature(sourceColorTemp);
275             targetColorTemp = target.getColorTemperature();
276         }
277         // mirek schema
278         MirekSchema targetMirekSchema = Objects.nonNull(targetColorTemp) ? targetColorTemp.getMirekSchema() : null;
279         MirekSchema sourceMirekSchema = Objects.nonNull(sourceColorTemp) ? sourceColorTemp.getMirekSchema() : null;
280         if (Objects.isNull(targetMirekSchema) && Objects.nonNull(sourceMirekSchema)) {
281             targetColorTemp = Objects.nonNull(targetColorTemp) ? targetColorTemp : new ColorTemperature();
282             targetColorTemp.setMirekSchema(sourceMirekSchema);
283         }
284         // metadata
285         MetaData targetMetaData = target.getMetaData();
286         MetaData sourceMetaData = source.getMetaData();
287         if (Objects.isNull(targetMetaData) && Objects.nonNull(sourceMetaData)) {
288             target.setMetadata(sourceMetaData);
289         }
290         // alerts
291         Alerts targetAlerts = target.getAlerts();
292         Alerts sourceAlerts = source.getAlerts();
293         if (Objects.isNull(targetAlerts) && Objects.nonNull(sourceAlerts)) {
294             target.setAlerts(sourceAlerts);
295         }
296         // effects
297         Effects targetEffects = target.getEffects();
298         Effects sourceEffects = source.getEffects();
299         if (Objects.isNull(targetEffects) && Objects.nonNull(sourceEffects)) {
300             targetEffects = sourceEffects;
301             target.setEffects(sourceEffects);
302             targetEffects = target.getEffects();
303         }
304         // effects values
305         List<String> targetStatusValues = Objects.nonNull(targetEffects) ? targetEffects.getStatusValues() : null;
306         List<String> sourceStatusValues = Objects.nonNull(sourceEffects) ? sourceEffects.getStatusValues() : null;
307         if (Objects.isNull(targetStatusValues) && Objects.nonNull(sourceStatusValues)) {
308             targetEffects = Objects.nonNull(targetEffects) ? targetEffects : new Effects();
309             targetEffects.setStatusValues(sourceStatusValues);
310         }
311         return target;
312     }
313 }