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