]> git.basschouten.com Git - openhab-addons.git/blob
ba07a9cc5ef571f4d5106faceab706e60b3f1e93
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.io.homekit.internal.accessories;
14
15 import static org.openhab.io.homekit.internal.HomekitCharacteristicType.*;
16
17 import java.math.BigDecimal;
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.Optional;
21 import java.util.concurrent.CompletableFuture;
22 import java.util.concurrent.ExecutionException;
23 import java.util.function.Function;
24 import java.util.function.Supplier;
25
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.openhab.io.homekit.internal.HomekitCharacteristicType;
28
29 import io.github.hapjava.characteristics.Characteristic;
30 import io.github.hapjava.characteristics.impl.airquality.AirQualityCharacteristic;
31 import io.github.hapjava.characteristics.impl.airquality.AirQualityEnum;
32 import io.github.hapjava.characteristics.impl.common.ActiveCharacteristic;
33 import io.github.hapjava.characteristics.impl.common.ActiveEnum;
34 import io.github.hapjava.characteristics.impl.common.ActiveIdentifierCharacteristic;
35 import io.github.hapjava.characteristics.impl.common.ConfiguredNameCharacteristic;
36 import io.github.hapjava.characteristics.impl.common.IdentifierCharacteristic;
37 import io.github.hapjava.characteristics.impl.common.IsConfiguredCharacteristic;
38 import io.github.hapjava.characteristics.impl.common.IsConfiguredEnum;
39 import io.github.hapjava.characteristics.impl.common.NameCharacteristic;
40 import io.github.hapjava.characteristics.impl.common.ServiceLabelIndexCharacteristic;
41 import io.github.hapjava.characteristics.impl.heatercooler.CurrentHeaterCoolerStateCharacteristic;
42 import io.github.hapjava.characteristics.impl.heatercooler.CurrentHeaterCoolerStateEnum;
43 import io.github.hapjava.characteristics.impl.heatercooler.TargetHeaterCoolerStateCharacteristic;
44 import io.github.hapjava.characteristics.impl.heatercooler.TargetHeaterCoolerStateEnum;
45 import io.github.hapjava.characteristics.impl.inputsource.CurrentVisibilityStateCharacteristic;
46 import io.github.hapjava.characteristics.impl.inputsource.CurrentVisibilityStateEnum;
47 import io.github.hapjava.characteristics.impl.inputsource.InputDeviceTypeCharacteristic;
48 import io.github.hapjava.characteristics.impl.inputsource.InputDeviceTypeEnum;
49 import io.github.hapjava.characteristics.impl.inputsource.InputSourceTypeCharacteristic;
50 import io.github.hapjava.characteristics.impl.inputsource.InputSourceTypeEnum;
51 import io.github.hapjava.characteristics.impl.television.ClosedCaptionsCharacteristic;
52 import io.github.hapjava.characteristics.impl.television.ClosedCaptionsEnum;
53 import io.github.hapjava.characteristics.impl.television.PictureModeCharacteristic;
54 import io.github.hapjava.characteristics.impl.television.PictureModeEnum;
55 import io.github.hapjava.characteristics.impl.television.SleepDiscoveryModeCharacteristic;
56 import io.github.hapjava.characteristics.impl.television.SleepDiscoveryModeEnum;
57 import io.github.hapjava.characteristics.impl.televisionspeaker.VolumeControlTypeCharacteristic;
58 import io.github.hapjava.characteristics.impl.televisionspeaker.VolumeControlTypeEnum;
59 import io.github.hapjava.characteristics.impl.thermostat.CurrentHeatingCoolingStateCharacteristic;
60 import io.github.hapjava.characteristics.impl.thermostat.CurrentHeatingCoolingStateEnum;
61 import io.github.hapjava.characteristics.impl.thermostat.TargetHeatingCoolingStateCharacteristic;
62 import io.github.hapjava.characteristics.impl.thermostat.TargetHeatingCoolingStateEnum;
63
64 /**
65  * Creates an optional characteristics from metadata
66  *
67  * @author Cody Cutrer - Initial contribution
68  */
69 @NonNullByDefault
70 public class HomekitMetadataCharacteristicFactory {
71
72     // List of optional characteristics that can be set via metadata, and the corresponding method to create them.
73     private static final Map<HomekitCharacteristicType, Function<Object, Characteristic>> OPTIONAL = new HashMap<>() {
74         {
75             put(ACTIVE_IDENTIFIER, HomekitMetadataCharacteristicFactory::createActiveIdentifierCharacteristic);
76             put(ACTIVE_STATUS, HomekitMetadataCharacteristicFactory::createActiveStatusCharacteristic);
77             put(AIR_QUALITY, HomekitMetadataCharacteristicFactory::createAirQualityCharacteristic);
78             put(CLOSED_CAPTIONS, HomekitMetadataCharacteristicFactory::createClosedCaptionsCharacteristic);
79             put(CONFIGURED, HomekitMetadataCharacteristicFactory::createIsConfiguredCharacteristic);
80             put(CONFIGURED_NAME, HomekitMetadataCharacteristicFactory::createConfiguredNameCharacteristic);
81             put(CURRENT_HEATER_COOLER_STATE,
82                     HomekitMetadataCharacteristicFactory::createCurrentHeaterCoolerStateCharacteristic);
83             put(CURRENT_HEATING_COOLING_STATE,
84                     HomekitMetadataCharacteristicFactory::createCurrentHeatingCoolingStateCharacteristic);
85             put(CURRENT_VISIBILITY, HomekitMetadataCharacteristicFactory::createCurrentVisibilityCharacteristic);
86             put(IDENTIFIER, HomekitMetadataCharacteristicFactory::createIdentifierCharacteristic);
87             put(INPUT_DEVICE_TYPE, HomekitMetadataCharacteristicFactory::createInputDeviceTypeCharacteristic);
88             put(INPUT_SOURCE_TYPE, HomekitMetadataCharacteristicFactory::createInputSourceTypeCharacteristic);
89             put(NAME, HomekitMetadataCharacteristicFactory::createNameCharacteristic);
90             put(PICTURE_MODE, HomekitMetadataCharacteristicFactory::createPictureModeCharacteristic);
91             put(SERVICE_INDEX, HomekitMetadataCharacteristicFactory::createServiceIndexCharacteristic);
92             put(SLEEP_DISCOVERY_MODE, HomekitMetadataCharacteristicFactory::createSleepDiscoveryModeCharacteristic);
93             put(TARGET_HEATER_COOLER_STATE,
94                     HomekitMetadataCharacteristicFactory::createTargetHeaterCoolerStateCharacteristic);
95             put(TARGET_HEATING_COOLING_STATE,
96                     HomekitMetadataCharacteristicFactory::createTargetHeatingCoolingStateCharacteristic);
97             put(VOLUME_CONTROL_TYPE, HomekitMetadataCharacteristicFactory::createVolumeControlTypeCharacteristic);
98         }
99     };
100
101     public static Optional<Characteristic> createCharacteristic(String characteristic, Object value) {
102         var type = HomekitCharacteristicType.valueOfTag(characteristic);
103         if (type.isEmpty() || !OPTIONAL.containsKey(type.get())) {
104             return Optional.empty();
105         }
106         return Optional.of(OPTIONAL.get(type.get()).apply(value));
107     }
108
109     private static Supplier<CompletableFuture<Integer>> getInteger(Object value) {
110         int intValue;
111         if (value instanceof BigDecimal valueAsBigDecimal) {
112             intValue = valueAsBigDecimal.intValue();
113         } else if (value instanceof Float) {
114             intValue = ((Float) value).intValue();
115         } else if (value instanceof Integer) {
116             intValue = (Integer) value;
117         } else if (value instanceof Long) {
118             intValue = ((Long) value).intValue();
119         } else {
120             intValue = Integer.valueOf(value.toString());
121         }
122         return () -> CompletableFuture.completedFuture(intValue);
123     }
124
125     private static Supplier<CompletableFuture<String>> getString(Object value) {
126         return () -> CompletableFuture.completedFuture(value.toString());
127     }
128
129     private static <T extends Enum<T>> Supplier<CompletableFuture<T>> getEnum(Object value, Class<T> klazz) {
130         T enumValue = Enum.valueOf(klazz, value.toString());
131         return () -> CompletableFuture.completedFuture(enumValue);
132     }
133
134     private static <T extends Enum<T>> Supplier<CompletableFuture<T>> getEnum(Object value, Class<T> klazz, T trueValue,
135             T falseValue) {
136         if (value.equals(true) || value.equals("true")) {
137             return () -> CompletableFuture.completedFuture(trueValue);
138         } else if (value.equals(false) || value.equals("false")) {
139             return () -> CompletableFuture.completedFuture(falseValue);
140         }
141         return getEnum(value, klazz);
142     }
143
144     private static Characteristic createActiveIdentifierCharacteristic(Object value) {
145         return new ActiveIdentifierCharacteristic(getInteger(value), v -> {
146         }, v -> {
147         }, () -> {
148         });
149     }
150
151     private static Characteristic createActiveStatusCharacteristic(Object value) {
152         return new ActiveCharacteristic(getEnum(value, ActiveEnum.class, ActiveEnum.ACTIVE, ActiveEnum.INACTIVE), v -> {
153         }, v -> {
154         }, () -> {
155         });
156     }
157
158     private static Characteristic createAirQualityCharacteristic(Object value) {
159         return new AirQualityCharacteristic(getEnum(value, AirQualityEnum.class), v -> {
160         }, () -> {
161         });
162     }
163
164     private static Characteristic createClosedCaptionsCharacteristic(Object value) {
165         return new ClosedCaptionsCharacteristic(
166                 getEnum(value, ClosedCaptionsEnum.class, ClosedCaptionsEnum.ENABLED, ClosedCaptionsEnum.DISABLED),
167                 v -> {
168                 }, v -> {
169                 }, () -> {
170                 });
171     }
172
173     private static Characteristic createIsConfiguredCharacteristic(Object value) {
174         return new IsConfiguredCharacteristic(
175                 getEnum(value, IsConfiguredEnum.class, IsConfiguredEnum.CONFIGURED, IsConfiguredEnum.NOT_CONFIGURED),
176                 v -> {
177                 }, v -> {
178                 }, () -> {
179                 });
180     }
181
182     private static Characteristic createConfiguredNameCharacteristic(Object value) {
183         return new ConfiguredNameCharacteristic(getString(value), v -> {
184         }, v -> {
185         }, () -> {
186         });
187     }
188
189     private static Characteristic createCurrentVisibilityCharacteristic(Object value) {
190         return new CurrentVisibilityStateCharacteristic(getEnum(value, CurrentVisibilityStateEnum.class,
191                 CurrentVisibilityStateEnum.SHOWN, CurrentVisibilityStateEnum.HIDDEN), v -> {
192                 }, () -> {
193                 });
194     }
195
196     private static Characteristic createCurrentHeaterCoolerStateCharacteristic(Object value) {
197         var enumSupplier = getEnum(value, CurrentHeaterCoolerStateEnum.class);
198         CurrentHeaterCoolerStateEnum enumValue;
199         try {
200             enumValue = enumSupplier.get().get();
201         } catch (InterruptedException | ExecutionException e) {
202             enumValue = CurrentHeaterCoolerStateEnum.INACTIVE;
203         }
204         return new CurrentHeaterCoolerStateCharacteristic(new CurrentHeaterCoolerStateEnum[] { enumValue },
205                 enumSupplier, v -> {
206                 }, () -> {
207                 });
208     }
209
210     private static Characteristic createCurrentHeatingCoolingStateCharacteristic(Object value) {
211         var enumSupplier = getEnum(value, CurrentHeatingCoolingStateEnum.class);
212         CurrentHeatingCoolingStateEnum enumValue;
213         try {
214             enumValue = enumSupplier.get().get();
215         } catch (InterruptedException | ExecutionException e) {
216             enumValue = CurrentHeatingCoolingStateEnum.OFF;
217         }
218         return new CurrentHeatingCoolingStateCharacteristic(new CurrentHeatingCoolingStateEnum[] { enumValue },
219                 enumSupplier, v -> {
220                 }, () -> {
221                 });
222     }
223
224     private static Characteristic createIdentifierCharacteristic(Object value) {
225         return new IdentifierCharacteristic(getInteger(value));
226     }
227
228     private static Characteristic createInputDeviceTypeCharacteristic(Object value) {
229         return new InputDeviceTypeCharacteristic(getEnum(value, InputDeviceTypeEnum.class), v -> {
230         }, () -> {
231         });
232     }
233
234     private static Characteristic createInputSourceTypeCharacteristic(Object value) {
235         return new InputSourceTypeCharacteristic(getEnum(value, InputSourceTypeEnum.class), v -> {
236         }, () -> {
237         });
238     }
239
240     private static Characteristic createNameCharacteristic(Object value) {
241         return new NameCharacteristic(getString(value));
242     }
243
244     private static Characteristic createPictureModeCharacteristic(Object value) {
245         return new PictureModeCharacteristic(getEnum(value, PictureModeEnum.class), v -> {
246         }, v -> {
247         }, () -> {
248         });
249     }
250
251     private static Characteristic createServiceIndexCharacteristic(Object value) {
252         return new ServiceLabelIndexCharacteristic(getInteger(value));
253     }
254
255     private static Characteristic createSleepDiscoveryModeCharacteristic(Object value) {
256         return new SleepDiscoveryModeCharacteristic(getEnum(value, SleepDiscoveryModeEnum.class,
257                 SleepDiscoveryModeEnum.ALWAYS_DISCOVERABLE, SleepDiscoveryModeEnum.NOT_DISCOVERABLE), v -> {
258                 }, () -> {
259                 });
260     }
261
262     private static Characteristic createTargetHeaterCoolerStateCharacteristic(Object value) {
263         var enumSupplier = getEnum(value, TargetHeaterCoolerStateEnum.class);
264         TargetHeaterCoolerStateEnum enumValue;
265         try {
266             enumValue = enumSupplier.get().get();
267         } catch (InterruptedException | ExecutionException e) {
268             enumValue = TargetHeaterCoolerStateEnum.AUTO;
269         }
270
271         return new TargetHeaterCoolerStateCharacteristic(new TargetHeaterCoolerStateEnum[] { enumValue }, enumSupplier,
272                 v -> {
273                 }, v -> {
274                 }, () -> {
275                 });
276     }
277
278     private static Characteristic createTargetHeatingCoolingStateCharacteristic(Object value) {
279         var enumSupplier = getEnum(value, TargetHeatingCoolingStateEnum.class);
280         TargetHeatingCoolingStateEnum enumValue;
281         try {
282             enumValue = enumSupplier.get().get();
283         } catch (InterruptedException | ExecutionException e) {
284             enumValue = TargetHeatingCoolingStateEnum.OFF;
285         }
286
287         return new TargetHeatingCoolingStateCharacteristic(new TargetHeatingCoolingStateEnum[] { enumValue },
288                 enumSupplier, v -> {
289                 }, v -> {
290                 }, () -> {
291                 });
292     }
293
294     private static Characteristic createVolumeControlTypeCharacteristic(Object value) {
295         return new VolumeControlTypeCharacteristic(getEnum(value, VolumeControlTypeEnum.class), v -> {
296         }, () -> {
297         });
298     }
299 }