]> git.basschouten.com Git - openhab-addons.git/blob
fcc4d030d5a2965af729dd8fa10aaca1dbf1dac6
[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.binding.tado.internal.adapter;
14
15 import java.math.BigDecimal;
16 import java.math.RoundingMode;
17 import java.time.OffsetDateTime;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.tado.internal.TadoBindingConstants.HvacMode;
22 import org.openhab.binding.tado.internal.TadoBindingConstants.OperationMode;
23 import org.openhab.binding.tado.internal.TadoBindingConstants.TemperatureUnit;
24 import org.openhab.binding.tado.swagger.codegen.api.model.ACFanLevel;
25 import org.openhab.binding.tado.swagger.codegen.api.model.ACHorizontalSwing;
26 import org.openhab.binding.tado.swagger.codegen.api.model.ACVerticalSwing;
27 import org.openhab.binding.tado.swagger.codegen.api.model.AcFanSpeed;
28 import org.openhab.binding.tado.swagger.codegen.api.model.AcPowerDataPoint;
29 import org.openhab.binding.tado.swagger.codegen.api.model.ActivityDataPoints;
30 import org.openhab.binding.tado.swagger.codegen.api.model.CoolingZoneSetting;
31 import org.openhab.binding.tado.swagger.codegen.api.model.GenericZoneSetting;
32 import org.openhab.binding.tado.swagger.codegen.api.model.HeatingZoneSetting;
33 import org.openhab.binding.tado.swagger.codegen.api.model.HotWaterZoneSetting;
34 import org.openhab.binding.tado.swagger.codegen.api.model.Overlay;
35 import org.openhab.binding.tado.swagger.codegen.api.model.OverlayTerminationConditionType;
36 import org.openhab.binding.tado.swagger.codegen.api.model.PercentageDataPoint;
37 import org.openhab.binding.tado.swagger.codegen.api.model.Power;
38 import org.openhab.binding.tado.swagger.codegen.api.model.SensorDataPoints;
39 import org.openhab.binding.tado.swagger.codegen.api.model.TadoSystemType;
40 import org.openhab.binding.tado.swagger.codegen.api.model.TemperatureDataPoint;
41 import org.openhab.binding.tado.swagger.codegen.api.model.TemperatureObject;
42 import org.openhab.binding.tado.swagger.codegen.api.model.TimerTerminationCondition;
43 import org.openhab.binding.tado.swagger.codegen.api.model.ZoneState;
44 import org.openhab.core.library.types.DateTimeType;
45 import org.openhab.core.library.types.DecimalType;
46 import org.openhab.core.library.types.OnOffType;
47 import org.openhab.core.library.types.QuantityType;
48 import org.openhab.core.library.types.StringType;
49 import org.openhab.core.library.unit.ImperialUnits;
50 import org.openhab.core.library.unit.SIUnits;
51 import org.openhab.core.library.unit.Units;
52 import org.openhab.core.types.State;
53 import org.openhab.core.types.UnDefType;
54
55 /**
56  * Adapter from API-level zone state to the binding's item-based zone state.
57  *
58  * @author Dennis Frommknecht - Initial contribution
59  * @author Andrew Fiddian-Green - Added Low Battery Alarm, A/C Power and Open Window channels
60  *
61  */
62 @NonNullByDefault
63 public class TadoZoneStateAdapter {
64     private final ZoneState zoneState;
65     private final TemperatureUnit temperatureUnit;
66
67     public TadoZoneStateAdapter(ZoneState zoneState, TemperatureUnit temperatureUnit) {
68         this.zoneState = zoneState;
69         this.temperatureUnit = temperatureUnit;
70     }
71
72     public State getInsideTemperature() {
73         SensorDataPoints sensorDataPoints = zoneState.getSensorDataPoints();
74         return toTemperatureState(sensorDataPoints.getInsideTemperature(), temperatureUnit);
75     }
76
77     public State getHumidity() {
78         PercentageDataPoint humidity = zoneState.getSensorDataPoints().getHumidity();
79         return humidity != null ? new QuantityType<>(humidity.getPercentage(), Units.PERCENT) : UnDefType.UNDEF;
80     }
81
82     public State getHeatingPower() {
83         ActivityDataPoints dataPoints = zoneState.getActivityDataPoints();
84         return dataPoints.getHeatingPower() != null
85                 ? new QuantityType<>(dataPoints.getHeatingPower().getPercentage().doubleValue(), Units.PERCENT)
86                 : UnDefType.UNDEF;
87     }
88
89     public State getAcPower() {
90         ActivityDataPoints dataPoints = zoneState.getActivityDataPoints();
91         AcPowerDataPoint acPower = dataPoints.getAcPower();
92         if (acPower != null) {
93             String acPowerValue = acPower.getValue();
94             if (acPowerValue != null) {
95                 return OnOffType.from(acPowerValue);
96             }
97         }
98         return UnDefType.UNDEF;
99     }
100
101     public StringType getMode() {
102         GenericZoneSetting setting = zoneState.getSetting();
103
104         if (!isPowerOn()) {
105             return StringType.valueOf(HvacMode.OFF.name());
106         } else if (setting.getType() == TadoSystemType.HEATING || setting.getType() == TadoSystemType.HOT_WATER) {
107             return StringType.valueOf(HvacMode.HEAT.name());
108         } else {
109             return StringType.valueOf(((CoolingZoneSetting) setting).getMode().getValue());
110         }
111     }
112
113     public State getTargetTemperature() {
114         if (!isPowerOn()) {
115             return UnDefType.UNDEF;
116         }
117         switch (zoneState.getSetting().getType()) {
118             case HEATING:
119                 return toTemperatureState(((HeatingZoneSetting) zoneState.getSetting()).getTemperature(),
120                         temperatureUnit);
121             case AIR_CONDITIONING:
122                 return toTemperatureState(((CoolingZoneSetting) zoneState.getSetting()).getTemperature(),
123                         temperatureUnit);
124             case HOT_WATER:
125                 return toTemperatureState(((HotWaterZoneSetting) zoneState.getSetting()).getTemperature(),
126                         temperatureUnit);
127             default:
128                 return UnDefType.UNDEF;
129         }
130     }
131
132     public State getFanSpeed() {
133         if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) {
134             AcFanSpeed result = ((CoolingZoneSetting) zoneState.getSetting()).getFanSpeed();
135             return result != null ? StringType.valueOf(result.getValue()) : UnDefType.NULL;
136         }
137         return UnDefType.UNDEF;
138     }
139
140     public State getSwing() {
141         if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) {
142             Power result = ((CoolingZoneSetting) zoneState.getSetting()).getSwing();
143             return result != null ? OnOffType.from(result == Power.ON) : UnDefType.NULL;
144         }
145         return UnDefType.UNDEF;
146     }
147
148     public State getFanLevel() {
149         if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) {
150             ACFanLevel result = ((CoolingZoneSetting) zoneState.getSetting()).getFanLevel();
151             return result != null ? StringType.valueOf(result.getValue()) : UnDefType.NULL;
152         }
153         return UnDefType.UNDEF;
154     }
155
156     public State getHorizontalSwing() {
157         if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) {
158             ACHorizontalSwing result = ((CoolingZoneSetting) zoneState.getSetting()).getHorizontalSwing();
159             return result != null ? StringType.valueOf(result.getValue()) : UnDefType.NULL;
160         }
161         return UnDefType.UNDEF;
162     }
163
164     public State getVerticalSwing() {
165         if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) {
166             ACVerticalSwing result = ((CoolingZoneSetting) zoneState.getSetting()).getVerticalSwing();
167             return result != null ? StringType.valueOf(result.getValue()) : UnDefType.NULL;
168         }
169         return UnDefType.UNDEF;
170     }
171
172     public StringType getOperationMode() {
173         Overlay overlay = zoneState.getOverlay();
174         if (overlay != null) {
175             switch (overlay.getTermination().getType()) {
176                 case MANUAL:
177                     return new StringType(OperationMode.MANUAL.name());
178                 case TIMER:
179                     return new StringType(OperationMode.TIMER.name());
180                 case TADO_MODE:
181                     return new StringType(OperationMode.UNTIL_CHANGE.name());
182             }
183         }
184
185         return new StringType(OperationMode.SCHEDULE.name());
186     }
187
188     public DecimalType getRemainingTimerDuration() {
189         Overlay overlay = zoneState.getOverlay();
190         if (overlay != null && overlay.getTermination().getType() == OverlayTerminationConditionType.TIMER) {
191             TimerTerminationCondition timerTerminationCondition = (TimerTerminationCondition) overlay.getTermination();
192
193             Integer remainingTimeInSeconds = timerTerminationCondition.getRemainingTimeInSeconds();
194             // If there's a timer overlay, then the timer should never be smaller than 1
195             return new DecimalType((int) Math.max(1.0, Math.round(remainingTimeInSeconds / 60.0)));
196         }
197
198         return new DecimalType();
199     }
200
201     public State getOverlayExpiration() {
202         Overlay overlay = zoneState.getOverlay();
203         if (overlay == null || overlay.getTermination().getProjectedExpiry() == null) {
204             return UnDefType.UNDEF;
205         }
206
207         return toDateTimeType(overlay.getTermination().getProjectedExpiry());
208     }
209
210     public boolean isPowerOn() {
211         Power power = Power.OFF;
212         GenericZoneSetting setting = zoneState.getSetting();
213
214         switch (setting.getType()) {
215             case HEATING:
216                 power = ((HeatingZoneSetting) setting).getPower();
217                 break;
218             case AIR_CONDITIONING:
219                 power = ((CoolingZoneSetting) setting).getPower();
220                 break;
221             case HOT_WATER:
222                 power = ((HotWaterZoneSetting) setting).getPower();
223                 break;
224         }
225
226         return "ON".equals(power.getValue());
227     }
228
229     private static DecimalType toDecimalType(double value) {
230         BigDecimal decimal = new BigDecimal(value).setScale(2, RoundingMode.HALF_UP);
231         return new DecimalType(decimal);
232     }
233
234     private static DateTimeType toDateTimeType(OffsetDateTime offsetDateTime) {
235         return new DateTimeType(offsetDateTime.toZonedDateTime());
236     }
237
238     private static State toTemperatureState(@Nullable TemperatureObject temperature, TemperatureUnit temperatureUnit) {
239         if (temperature == null || (temperature.getCelsius() == null && temperature.getFahrenheit() == null)) {
240             return UnDefType.UNDEF;
241         }
242         return temperatureUnit == TemperatureUnit.FAHRENHEIT
243                 ? new QuantityType<>(temperature.getFahrenheit(), ImperialUnits.FAHRENHEIT)
244                 : new QuantityType<>(temperature.getCelsius(), SIUnits.CELSIUS);
245     }
246
247     private static State toTemperatureState(@Nullable TemperatureDataPoint temperature,
248             TemperatureUnit temperatureUnit) {
249         if (temperature == null || (temperature.getCelsius() == null && temperature.getFahrenheit() == null)) {
250             return UnDefType.UNDEF;
251         }
252         return temperatureUnit == TemperatureUnit.FAHRENHEIT
253                 ? new QuantityType<>(temperature.getFahrenheit(), ImperialUnits.FAHRENHEIT)
254                 : new QuantityType<>(temperature.getCelsius(), SIUnits.CELSIUS);
255     }
256
257     public State getOpenWindowDetected() {
258         Boolean openWindowDetected = zoneState.isOpenWindowDetected();
259         if (openWindowDetected != null) {
260             return OnOffType.from(openWindowDetected);
261         }
262         return OnOffType.OFF;
263     }
264
265     public State getLight() {
266         if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) {
267             Power result = ((CoolingZoneSetting) zoneState.getSetting()).getLight();
268             return result != null ? OnOffType.from(result == Power.ON) : UnDefType.NULL;
269         }
270         return UnDefType.UNDEF;
271     }
272 }