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