]> git.basschouten.com Git - openhab-addons.git/blob
3aa396261a48609b3ef23a0e202501cf764d6625
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.ACTIVE_STATUS;
16 import static org.openhab.io.homekit.internal.HomekitCharacteristicType.CURRENT_HEATER_COOLER_STATE;
17 import static org.openhab.io.homekit.internal.HomekitCharacteristicType.TARGET_HEATER_COOLER_STATE;
18
19 import java.util.ArrayList;
20 import java.util.EnumMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Optional;
24 import java.util.concurrent.CompletableFuture;
25
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.openhab.core.items.GenericItem;
28 import org.openhab.core.library.items.StringItem;
29 import org.openhab.core.library.types.DecimalType;
30 import org.openhab.core.library.types.OnOffType;
31 import org.openhab.core.library.types.OpenClosedType;
32 import org.openhab.core.library.types.StringType;
33 import org.openhab.io.homekit.internal.HomekitAccessoryUpdater;
34 import org.openhab.io.homekit.internal.HomekitCharacteristicType;
35 import org.openhab.io.homekit.internal.HomekitSettings;
36 import org.openhab.io.homekit.internal.HomekitTaggedItem;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import io.github.hapjava.accessories.HeaterCoolerAccessory;
41 import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback;
42 import io.github.hapjava.characteristics.impl.heatercooler.CurrentHeaterCoolerStateEnum;
43 import io.github.hapjava.characteristics.impl.heatercooler.TargetHeaterCoolerStateEnum;
44 import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitCharacteristic;
45 import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitEnum;
46 import io.github.hapjava.services.impl.HeaterCoolerService;
47
48 /**
49  * Implements Heater Cooler
50  *
51  * @author Eugen Freiter - Initial contribution
52  */
53
54 public class HomekitHeaterCoolerImpl extends AbstractHomekitAccessoryImpl implements HeaterCoolerAccessory {
55     private final Logger logger = LoggerFactory.getLogger(HomekitHeaterCoolerImpl.class);
56     private final BooleanItemReader activeReader;
57     private final Map<CurrentHeaterCoolerStateEnum, String> currentStateMapping = new EnumMap<CurrentHeaterCoolerStateEnum, String>(
58             CurrentHeaterCoolerStateEnum.class) {
59         {
60             put(CurrentHeaterCoolerStateEnum.INACTIVE, "INACTIVE");
61             put(CurrentHeaterCoolerStateEnum.IDLE, "IDLE");
62             put(CurrentHeaterCoolerStateEnum.HEATING, "HEATING");
63             put(CurrentHeaterCoolerStateEnum.COOLING, "COOLING");
64         }
65     };
66     private final Map<TargetHeaterCoolerStateEnum, String> targetStateMapping = new EnumMap<TargetHeaterCoolerStateEnum, String>(
67             TargetHeaterCoolerStateEnum.class) {
68         {
69             put(TargetHeaterCoolerStateEnum.AUTO, "AUTO");
70             put(TargetHeaterCoolerStateEnum.HEAT, "HEAT");
71             put(TargetHeaterCoolerStateEnum.COOL, "COOL");
72         }
73     };
74
75     private final List<CurrentHeaterCoolerStateEnum> customCurrentStateList = new ArrayList<>();
76     private final List<TargetHeaterCoolerStateEnum> customTargetStateList = new ArrayList<>();
77
78     public HomekitHeaterCoolerImpl(HomekitTaggedItem taggedItem, List<HomekitTaggedItem> mandatoryCharacteristics,
79             HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException {
80         super(taggedItem, mandatoryCharacteristics, updater, settings);
81         activeReader = new BooleanItemReader(getItem(ACTIVE_STATUS, GenericItem.class)
82                 .orElseThrow(() -> new IncompleteAccessoryException(ACTIVE_STATUS)), OnOffType.ON, OpenClosedType.OPEN);
83         updateMapping(CURRENT_HEATER_COOLER_STATE, currentStateMapping, customCurrentStateList);
84         updateMapping(TARGET_HEATER_COOLER_STATE, targetStateMapping, customTargetStateList);
85         final HeaterCoolerService service = new HeaterCoolerService(this);
86         service.addOptionalCharacteristic(new TemperatureDisplayUnitCharacteristic(this::getTemperatureDisplayUnit,
87                 this::setTemperatureDisplayUnit, this::subscribeTemperatureDisplayUnit,
88                 this::unsubscribeTemperatureDisplayUnit));
89         getServices().add(service);
90     }
91
92     @Override
93     public CurrentHeaterCoolerStateEnum[] getCurrentHeaterCoolerStateValidValues() {
94         return customCurrentStateList.isEmpty()
95                 ? currentStateMapping.keySet().toArray(new CurrentHeaterCoolerStateEnum[0])
96                 : customCurrentStateList.toArray(new CurrentHeaterCoolerStateEnum[0]);
97     }
98
99     @Override
100     public TargetHeaterCoolerStateEnum[] getTargetHeaterCoolerStateValidValues() {
101         return customTargetStateList.isEmpty() ? targetStateMapping.keySet().toArray(new TargetHeaterCoolerStateEnum[0])
102                 : customTargetStateList.toArray(new TargetHeaterCoolerStateEnum[0]);
103     }
104
105     @Override
106     public CompletableFuture<Double> getCurrentTemperature() {
107         final @Nullable DecimalType state = getStateAs(HomekitCharacteristicType.CURRENT_TEMPERATURE,
108                 DecimalType.class);
109         return CompletableFuture.completedFuture(state != null ? convertToCelsius(state.doubleValue()) : 0.0);
110     }
111
112     @Override
113     public CompletableFuture<Boolean> isActive() {
114         return CompletableFuture.completedFuture(activeReader.getValue());
115     }
116
117     @Override
118     public CompletableFuture<Void> setActive(boolean state) {
119         activeReader.setValue(state);
120         return CompletableFuture.completedFuture(null);
121     }
122
123     @Override
124     public CompletableFuture<CurrentHeaterCoolerStateEnum> getCurrentHeaterCoolerState() {
125         return CompletableFuture.completedFuture(getKeyFromMapping(CURRENT_HEATER_COOLER_STATE, currentStateMapping,
126                 CurrentHeaterCoolerStateEnum.INACTIVE));
127     }
128
129     @Override
130     public CompletableFuture<TargetHeaterCoolerStateEnum> getTargetHeaterCoolerState() {
131         return CompletableFuture.completedFuture(
132                 getKeyFromMapping(TARGET_HEATER_COOLER_STATE, targetStateMapping, TargetHeaterCoolerStateEnum.AUTO));
133     }
134
135     @Override
136     public CompletableFuture<Void> setTargetHeaterCoolerState(TargetHeaterCoolerStateEnum state) {
137         final Optional<HomekitTaggedItem> characteristic = getCharacteristic(
138                 HomekitCharacteristicType.TARGET_HEATER_COOLER_STATE);
139         if (characteristic.isPresent()) {
140             ((StringItem) characteristic.get().getItem()).send(new StringType(targetStateMapping.get(state)));
141         } else {
142             logger.warn("Missing mandatory characteristic {}",
143                     HomekitCharacteristicType.TARGET_HEATING_COOLING_STATE.getTag());
144         }
145         return CompletableFuture.completedFuture(null);
146     }
147
148     public CompletableFuture<TemperatureDisplayUnitEnum> getTemperatureDisplayUnit() {
149         return CompletableFuture
150                 .completedFuture(getSettings().useFahrenheitTemperature ? TemperatureDisplayUnitEnum.FAHRENHEIT
151                         : TemperatureDisplayUnitEnum.CELSIUS);
152     }
153
154     public void setTemperatureDisplayUnit(TemperatureDisplayUnitEnum value) {
155         // temperature unit set globally via binding setting and cannot be changed at item level.
156         // this method is intentionally empty.
157     }
158
159     @Override
160     public void subscribeCurrentHeaterCoolerState(HomekitCharacteristicChangeCallback callback) {
161         subscribe(HomekitCharacteristicType.CURRENT_HEATER_COOLER_STATE, callback);
162     }
163
164     @Override
165     public void unsubscribeCurrentHeaterCoolerState() {
166         unsubscribe(HomekitCharacteristicType.CURRENT_HEATER_COOLER_STATE);
167     }
168
169     @Override
170     public void subscribeTargetHeaterCoolerState(HomekitCharacteristicChangeCallback callback) {
171         subscribe(HomekitCharacteristicType.TARGET_HEATER_COOLER_STATE, callback);
172     }
173
174     @Override
175     public void unsubscribeTargetHeaterCoolerState() {
176         unsubscribe(HomekitCharacteristicType.TARGET_HEATER_COOLER_STATE);
177     }
178
179     @Override
180     public void subscribeActive(HomekitCharacteristicChangeCallback callback) {
181         subscribe(ACTIVE_STATUS, callback);
182     }
183
184     @Override
185     public void unsubscribeActive() {
186         unsubscribe(ACTIVE_STATUS);
187     }
188
189     @Override
190     public void subscribeCurrentTemperature(HomekitCharacteristicChangeCallback callback) {
191         subscribe(HomekitCharacteristicType.CURRENT_TEMPERATURE, callback);
192     }
193
194     @Override
195     public void unsubscribeCurrentTemperature() {
196         unsubscribe(HomekitCharacteristicType.CURRENT_TEMPERATURE);
197     }
198
199     public void subscribeTemperatureDisplayUnit(HomekitCharacteristicChangeCallback callback) {
200         // temperature unit set globally via binding setting and cannot be changed at item level.
201         // this method is intentionally empty
202     }
203
204     public void unsubscribeTemperatureDisplayUnit() {
205         // temperature unit set globally via binding setting and cannot be changed at item level.
206         // this method is intentionally empty
207     }
208 }