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