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