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