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