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