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