]> git.basschouten.com Git - openhab-addons.git/blob
49ad294b4e1630a37aa61a371b22dd952e531a8a
[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.CURRENT_DOOR_STATE;
16 import static org.openhab.io.homekit.internal.HomekitCharacteristicType.OBSTRUCTION_STATUS;
17 import static org.openhab.io.homekit.internal.HomekitCharacteristicType.TARGET_DOOR_STATE;
18
19 import java.util.List;
20 import java.util.Optional;
21 import java.util.concurrent.CompletableFuture;
22
23 import org.openhab.core.items.Item;
24 import org.openhab.core.library.items.StringItem;
25 import org.openhab.core.library.items.SwitchItem;
26 import org.openhab.core.library.types.OnOffType;
27 import org.openhab.core.library.types.StringType;
28 import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
29 import org.openhab.io.homekit.internal.HomekitOHItemProxy;
30 import org.openhab.io.homekit.internal.HomekitSettings;
31 import org.openhab.io.homekit.internal.HomekitTaggedItem;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import io.github.hapjava.accessories.GarageDoorOpenerAccessory;
36 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
37 import io.github.hapjava.characteristics.impl.garagedoor.CurrentDoorStateEnum;
38 import io.github.hapjava.characteristics.impl.garagedoor.TargetDoorStateEnum;
39 import io.github.hapjava.services.impl.GarageDoorOpenerService;
40
41 /**
42  * Implements Garage Door Opener
43  *
44  * @author Eugen Freiter - Initial contribution
45  */
46 public class HomekitGarageDoorOpenerImpl extends AbstractHomekitAccessoryImpl implements GarageDoorOpenerAccessory {
47     private final Logger logger = LoggerFactory.getLogger(HomekitGarageDoorOpenerImpl.class);
48     private final BooleanItemReader obstructionReader;
49
50     public HomekitGarageDoorOpenerImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
51             HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
52         super(taggedItem, mandatoryCharacteristics, updater, settings);
53         obstructionReader = createBooleanReader(OBSTRUCTION_STATUS);
54         getServices().add(new GarageDoorOpenerService(this));
55     }
56
57     @Override
58     public CompletableFuture<CurrentDoorStateEnum> getCurrentDoorState() {
59         final Optional<HomekitTaggedItem> characteristic = getCharacteristic(CURRENT_DOOR_STATE);
60         final HomekitSettings settings = getSettings();
61         String stringValue = settings.doorCurrentStateClosed;
62         if (characteristic.isPresent()) {
63             stringValue = characteristic.get().getItem().getState().toString();
64         } else {
65             logger.warn("Missing mandatory characteristic {}", CURRENT_DOOR_STATE);
66         }
67         CurrentDoorStateEnum mode;
68
69         if (stringValue.equalsIgnoreCase(settings.doorCurrentStateClosed)) {
70             mode = CurrentDoorStateEnum.CLOSED;
71         } else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateClosing)) {
72             mode = CurrentDoorStateEnum.CLOSING;
73         } else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateOpen)) {
74             mode = CurrentDoorStateEnum.OPEN;
75         } else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateOpening)) {
76             mode = CurrentDoorStateEnum.OPENING;
77         } else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateStopped)) {
78             mode = CurrentDoorStateEnum.STOPPED;
79         } else if (stringValue.equals("UNDEF") || stringValue.equals("NULL")) {
80             logger.warn("Current door state not available. Relaying value of CLOSED to HomeKit");
81             mode = CurrentDoorStateEnum.CLOSED;
82         } else {
83             logger.warn("Unrecognized current door state: {}. Expected {}, {}, {}, {} or {} strings in value.",
84                     stringValue, settings.doorCurrentStateClosed, settings.doorCurrentStateClosing,
85                     settings.doorCurrentStateOpen, settings.doorCurrentStateOpening, settings.doorCurrentStateStopped);
86             mode = CurrentDoorStateEnum.CLOSED;
87         }
88         return CompletableFuture.completedFuture(mode);
89     }
90
91     @Override
92     public CompletableFuture<TargetDoorStateEnum> getTargetDoorState() {
93         final Optional<HomekitTaggedItem> characteristic = getCharacteristic(TARGET_DOOR_STATE);
94         Item item;
95
96         if (characteristic.isPresent()) {
97             item = characteristic.get().getItem();
98         } else {
99             logger.warn("Missing mandatory characteristic {}", TARGET_DOOR_STATE);
100             return CompletableFuture.completedFuture(TargetDoorStateEnum.CLOSED);
101         }
102         TargetDoorStateEnum mode;
103
104         final Item baseItem = HomekitOHItemProxy.getBaseItem(item);
105         if (baseItem instanceof SwitchItem) {
106             mode = item.getState() == OnOffType.ON ? TargetDoorStateEnum.OPEN : TargetDoorStateEnum.CLOSED;
107         } else if (baseItem instanceof StringItem) {
108             final HomekitSettings settings = getSettings();
109             final String stringValue = item.getState().toString();
110             if (stringValue.equalsIgnoreCase(settings.doorTargetStateClosed)) {
111                 mode = TargetDoorStateEnum.CLOSED;
112             } else if (stringValue.equalsIgnoreCase(settings.doorTargetStateOpen)) {
113                 mode = TargetDoorStateEnum.OPEN;
114             } else {
115                 logger.warn(
116                         "Unsupported value {} for {}. Only {} and {} supported. Check HomeKit settings if you want to change the mapping",
117                         stringValue, item.getName(), settings.doorTargetStateClosed, settings.doorTargetStateOpen);
118                 mode = TargetDoorStateEnum.CLOSED;
119             }
120         } else {
121             logger.warn("Unsupported item type {} for {}. Only Switch and String are supported", baseItem.getType(),
122                     item.getName());
123             mode = TargetDoorStateEnum.CLOSED;
124         }
125         return CompletableFuture.completedFuture(mode);
126     }
127
128     @Override
129     public CompletableFuture<Boolean> getObstructionDetected() {
130         return CompletableFuture.completedFuture(obstructionReader.getValue());
131     }
132
133     @Override
134     public CompletableFuture<Void> setTargetDoorState(TargetDoorStateEnum targetDoorStateEnum) {
135         final Optional<HomekitTaggedItem> characteristic = getCharacteristic(TARGET_DOOR_STATE);
136         final HomekitTaggedItem taggedItem;
137         if (characteristic.isPresent()) {
138             taggedItem = characteristic.get();
139         } else {
140             logger.warn("Missing mandatory characteristic {}", TARGET_DOOR_STATE);
141             return CompletableFuture.completedFuture(null);
142         }
143
144         if (taggedItem.getBaseItem() instanceof SwitchItem) {
145             taggedItem.send(OnOffType.from(targetDoorStateEnum == TargetDoorStateEnum.OPEN));
146         } else if (taggedItem.getBaseItem() instanceof StringItem) {
147             final HomekitSettings settings = getSettings();
148             taggedItem
149                     .send(new StringType(targetDoorStateEnum == TargetDoorStateEnum.OPEN ? settings.doorTargetStateOpen
150                             : settings.doorTargetStateClosed));
151         } else {
152             logger.warn("Unsupported item type {} for {}. Only Switch and String are supported",
153                     taggedItem.getBaseItem().getType(), taggedItem.getName());
154         }
155         return CompletableFuture.completedFuture(null);
156     }
157
158     @Override
159     public void subscribeCurrentDoorState(HomekitCharacteristicChangeCallback callback) {
160         subscribe(CURRENT_DOOR_STATE, callback);
161     }
162
163     @Override
164     public void subscribeTargetDoorState(HomekitCharacteristicChangeCallback callback) {
165         subscribe(TARGET_DOOR_STATE, callback);
166     }
167
168     @Override
169     public void subscribeObstructionDetected(HomekitCharacteristicChangeCallback callback) {
170         subscribe(OBSTRUCTION_STATUS, callback);
171     }
172
173     @Override
174     public void unsubscribeCurrentDoorState() {
175         unsubscribe(CURRENT_DOOR_STATE);
176     }
177
178     @Override
179     public void unsubscribeTargetDoorState() {
180         unsubscribe(TARGET_DOOR_STATE);
181     }
182
183     @Override
184     public void unsubscribeObstructionDetected() {
185         unsubscribe(OBSTRUCTION_STATUS);
186     }
187 }