diff --git a/bundles/org.openhab.binding.tado/README.md b/bundles/org.openhab.binding.tado/README.md index 69c03afdac7..b33aac7a0a8 100644 --- a/bundles/org.openhab.binding.tado/README.md +++ b/bundles/org.openhab.binding.tado/README.md @@ -27,7 +27,7 @@ Afterwards the discovery will show all zones and mobile devices associated with ### Channels Name | Type | Description | Read/Write --|-|-|-|- +-|-|-|- `homePresence` | String | Current presence value of the tado home. `HOME` and `AWAY` can be set | RW ## `zone` Thing @@ -70,16 +70,34 @@ Name | Type | Description | Read/Write | Zone type `acPower` | Switch | Indicates if the Air-Conditioning is Off or On | R | `AC` `hvacMode` | String | Active mode, one of `OFF`, `HEAT`, `COOL`, `DRY`, `FAN`, `AUTO` | RW | `HEATING` and `DHW` support `OFF` and `HEAT`, `AC` can support more `targetTemperature` | Number:Temperature | Set point | RW | `HEATING`, `AC`, `DHW` -`fanspeed` | String | Fan speed, one of `AUTO`, `LOW`, `MIDDLE`, `HIGH` | RW | `AC` -`swing` | Switch | Swing on/off | RW | `AC` +`fanspeed`1) | String | Fan speed, one of `AUTO`, `LOW`, `MIDDLE`, `HIGH` | RW | `AC` +`fanLevel`1) | String | Fan speed, one of 3) `AUTO`, `SILENT`, `LEVEL1`, `LEVEL2`, `LEVEL3`, `LEVEL4`, `LEVEL5` | RW | `AC` +`swing`2) | Switch | Swing on/off | RW | `AC` +`verticalSwing`2) | String | Vertical swing state, one of 3) `OFF`, `ON`, `UP`, `MID_UP`, `MID`, `MID_DOWN`, `DOWN`, `AUTO` | RW | `AC` +`horizontalSwing`2) | String | Horizontal swing state, one of 3) `OFF`, `ON`, `LEFT`, `MID_LEFT`, `MID`, `MID_RIGHT`, `RIGHT`, `AUTO` | RW | `AC` `overlayExpiry` | DateTime | End date and time of a timer | R | `HEATING`, `AC`, `DHW` `timerDuration` | Number | Timer duration in minutes | RW | `HEATING`, `AC`, `DHW` `operationMode` | String | Operation mode the zone is currently in. One of `SCHEDULE` (follow smart schedule), `MANUAL` (override until ended manually), `TIMER` (override for a given time), `UNTIL_CHANGE` (active until next smart schedule block or until AWAY mode becomes active) | RW | `HEATING`, `AC`, `DHW` `batteryLowAlarm` | Switch | A control device in the Zone has a low battery (if applicable) | R | Any Zone `openWindowDetected` | Switch | An open window has been detected in the Zone | R | Any Zone +`light` | Switch | State (`ON`, `OFF`) of the control panel light (if applicable) | RW | `AC` The `RW` items are used to either override the schedule or to return to it (if `hvacMode` is set to `SCHEDULE`). +1) Simpler A/C units have fan speed settings in the range [`LOW`, `MIDDLE`, `HIGH`]. +However, more sophisticated devices have settings in the range [`SILENT`, `LEVEL1`, `LEVEL2`, `LEVEL3`, `LEVEL4`]. +So you need to choose the respective channel type name that matches the features of your device. + +2) Simpler A/C units have a single switch type swing function that is either `ON` or `OFF`. +However, more sophisticated devices may have either a vertical swing, a horizontal swing, or both, which could also have more complex settings. +For example the horizontal swing function could simply be `ON` or it could have more complex settings in the range [`LEFT`, `MID_LEFT`, `MID`, `MID_RIGHT`, `RIGHT`]. +So you need to choose the respective channel type name that matches the features of your device. + +3) The _'one of'_ list contains all possible state values supported within the tado° binding. +However, in reality different A/C units might only support a **_subset_** of those values. +And indeed the subset of supported values might depend on the current state of the `acPower` and `hvacMode` channels. +In that case, if you send a channel command value to an A/C unit which does not (currently) support that particular state value, then openHAB will report a '422' run-time error in the log. + ### Item Command Collection Item changes are not immediately applied, but instead collected and only when no change is done for 5 seconds (by default - see `hvacChangeDebounce` above), the combined HVAC change is sent to the server. diff --git a/bundles/org.openhab.binding.tado/src/main/api/tado-api.yaml b/bundles/org.openhab.binding.tado/src/main/api/tado-api.yaml index 53d21c9579d..05226ae6ce7 100644 --- a/bundles/org.openhab.binding.tado/src/main/api/tado-api.yaml +++ b/bundles/org.openhab.binding.tado/src/main/api/tado-api.yaml @@ -552,6 +552,44 @@ definitions: - HIGH - AUTO + ACFanLevel: + type: string + description: Cooling system fan speed. + enum: + - SILENT + - LEVEL1 + - LEVEL2 + - LEVEL3 + - LEVEL4 + - LEVEL5 + - AUTO + + ACHorizontalSwing: + type: string + description: Horizontal swing. + enum: + - 'OFF' + - 'ON' + - LEFT + - MID_LEFT + - MID + - MID_RIGHT + - RIGHT + - AUTO + + ACVerticalSwing: + type: string + description: Vertical swing. + enum: + - 'OFF' + - 'ON' + - UP + - MID_UP + - MID + - MID_DOWN + - DOWN + - AUTO + AcMode: type: string description: Cooling system mode. @@ -582,6 +620,18 @@ definitions: swing: description: Whether the angle of the air stream should be fixed or not, if power is `ON` and configuring this is supported in this AC mode. $ref: "#/definitions/Power" + light: + description: State of the control panel light. + $ref: "#/definitions/Power" + fanLevel: + description: The desired fan speed level, if power is `ON` and fan speeds are supported in this AC mode. + $ref: "#/definitions/ACFanLevel" + verticalSwing: + description: Whether the angle of the vertical air stream should be fixed or not, if power is `ON` and configuring this is supported in this AC mode. And if it is fixed, determines the respective position. + $ref: "#/definitions/ACVerticalSwing" + horizontalSwing: + description: Whether the angle of the horizontal air stream should be fixed or not, if power is `ON` and configuring this is supported in this AC mode. And if it is fixed, determines the respective position. + $ref: "#/definitions/ACHorizontalSwing" required: - power @@ -981,15 +1031,35 @@ definitions: temperatures: $ref: "#/definitions/TemperatureRange" fanSpeeds: - description: Cooling system fan speed. + description: Cooling system fan speeds. type: array items: $ref: "#/definitions/AcFanSpeed" swings: - description: Cooling system swing mode. + description: Cooling system swing modes. type: array items: $ref: "#/definitions/Power" + light: + description: Control panel light state. (Tado confusingly names this array without an 's') + type: array + items: + $ref: "#/definitions/Power" + fanLevel: + description: Cooling system fan speeds. (Tado confusingly names this array without an 's') + type: array + items: + $ref: "#/definitions/ACFanLevel" + horizontalSwing: + description: Cooling system horizontal swing modes. (Tado confusingly names this array without an 's') + type: array + items: + $ref: "#/definitions/ACHorizontalSwing" + verticalSwing: + description: Cooling system vertical swing modes. (Tado confusingly names this array without an 's') + type: array + items: + $ref: "#/definitions/ACVerticalSwing" HeatingCapabilities: x-discriminator-value: HEATING diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/TadoBindingConstants.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/TadoBindingConstants.java index e52f3578ab1..e1fa6e03916 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/TadoBindingConstants.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/TadoBindingConstants.java @@ -65,6 +65,8 @@ public class TadoBindingConstants { public static final String CHANNEL_ZONE_SWING = "swing"; + public static final String CHANNEL_ZONE_LIGHT = "light"; + public static final String CHANNEL_ZONE_FAN_SPEED = "fanspeed"; public static enum FanSpeed { @@ -74,6 +76,44 @@ public class TadoBindingConstants { AUTO } + public static final String CHANNEL_ZONE_FAN_LEVEL = "fanLevel"; + + public static enum FanLevel { + SILENT, + LEVEL1, + LEVEL2, + LEVEL3, + LEVEL4, + LEVEL5, + AUTO + } + + public static final String CHANNEL_ZONE_HORIZONTAL_SWING = "horizontalSwing"; + + public static enum HorizontalSwing { + OFF, + ON, + LEFT, + MID_LEFT, + MID, + MID_RIGHT, + RIGHT, + AUTO + } + + public static final String CHANNEL_ZONE_VERTICAL_SWING = "verticalSwing"; + + public static enum VerticalSwing { + OFF, + ON, + UP, + MID_UP, + MID, + MID_DOWN, + DOWN, + AUTO + } + public static final String CHANNEL_ZONE_OPERATION_MODE = "operationMode"; public static enum OperationMode { diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/TadoHvacChange.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/TadoHvacChange.java index cc9f509edcc..de47df19fcb 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/TadoHvacChange.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/TadoHvacChange.java @@ -14,9 +14,12 @@ package org.openhab.binding.tado.internal; import java.io.IOException; +import org.openhab.binding.tado.internal.TadoBindingConstants.FanLevel; import org.openhab.binding.tado.internal.TadoBindingConstants.FanSpeed; +import org.openhab.binding.tado.internal.TadoBindingConstants.HorizontalSwing; import org.openhab.binding.tado.internal.TadoBindingConstants.HvacMode; import org.openhab.binding.tado.internal.TadoBindingConstants.OperationMode; +import org.openhab.binding.tado.internal.TadoBindingConstants.VerticalSwing; import org.openhab.binding.tado.internal.api.ApiException; import org.openhab.binding.tado.internal.api.model.GenericZoneSetting; import org.openhab.binding.tado.internal.api.model.Overlay; @@ -115,6 +118,21 @@ public class TadoHvacChange { return this; } + public TadoHvacChange withFanLevel(FanLevel fanLevel) { + settingsBuilder.withFanLevel(fanLevel); + return this; + } + + public TadoHvacChange withHorizontalSwing(HorizontalSwing horizontalSwing) { + settingsBuilder.withHorizontalSwing(horizontalSwing); + return this; + } + + public TadoHvacChange withVerticalSwing(VerticalSwing verticalSwing) { + settingsBuilder.withVerticalSwing(verticalSwing); + return this; + } + public void apply() throws IOException, ApiException { if (followSchedule) { zoneHandler.removeOverlay(); @@ -135,4 +153,9 @@ public class TadoHvacChange { return overlay; } + + public TadoHvacChange withLight(boolean lightOn) { + settingsBuilder.withLight(lightOn); + return this; + } } diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/adapter/TadoZoneStateAdapter.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/adapter/TadoZoneStateAdapter.java index 7c6148a1b66..4e80dc9f08a 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/adapter/TadoZoneStateAdapter.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/adapter/TadoZoneStateAdapter.java @@ -19,6 +19,10 @@ import java.time.OffsetDateTime; import org.openhab.binding.tado.internal.TadoBindingConstants.HvacMode; import org.openhab.binding.tado.internal.TadoBindingConstants.OperationMode; import org.openhab.binding.tado.internal.TadoBindingConstants.TemperatureUnit; +import org.openhab.binding.tado.internal.api.model.ACFanLevel; +import org.openhab.binding.tado.internal.api.model.ACHorizontalSwing; +import org.openhab.binding.tado.internal.api.model.ACVerticalSwing; +import org.openhab.binding.tado.internal.api.model.AcFanSpeed; import org.openhab.binding.tado.internal.api.model.AcPowerDataPoint; import org.openhab.binding.tado.internal.api.model.ActivityDataPoints; import org.openhab.binding.tado.internal.api.model.CoolingZoneSetting; @@ -119,27 +123,42 @@ public class TadoZoneStateAdapter { public State getFanSpeed() { if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) { - CoolingZoneSetting setting = (CoolingZoneSetting) zoneState.getSetting(); - return setting.getFanSpeed() != null ? StringType.valueOf(setting.getFanSpeed().getValue()) - : UnDefType.NULL; - } else { - return UnDefType.UNDEF; + AcFanSpeed result = ((CoolingZoneSetting) zoneState.getSetting()).getFanSpeed(); + return result != null ? StringType.valueOf(result.getValue()) : UnDefType.NULL; } + return UnDefType.UNDEF; } public State getSwing() { if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) { - CoolingZoneSetting setting = (CoolingZoneSetting) zoneState.getSetting(); - if (setting.getSwing() == null) { - return UnDefType.NULL; - } else if (setting.getSwing() == Power.ON) { - return OnOffType.ON; - } else { - return OnOffType.OFF; - } - } else { - return UnDefType.UNDEF; + Power result = ((CoolingZoneSetting) zoneState.getSetting()).getSwing(); + return result != null ? OnOffType.from(result == Power.ON) : UnDefType.NULL; } + return UnDefType.UNDEF; + } + + public State getFanLevel() { + if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) { + ACFanLevel result = ((CoolingZoneSetting) zoneState.getSetting()).getFanLevel(); + return result != null ? StringType.valueOf(result.getValue()) : UnDefType.NULL; + } + return UnDefType.UNDEF; + } + + public State getHorizontalSwing() { + if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) { + ACHorizontalSwing result = ((CoolingZoneSetting) zoneState.getSetting()).getHorizontalSwing(); + return result != null ? StringType.valueOf(result.getValue()) : UnDefType.NULL; + } + return UnDefType.UNDEF; + } + + public State getVerticalSwing() { + if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) { + ACVerticalSwing result = ((CoolingZoneSetting) zoneState.getSetting()).getVerticalSwing(); + return result != null ? StringType.valueOf(result.getValue()) : UnDefType.NULL; + } + return UnDefType.UNDEF; } public StringType getOperationMode() { @@ -235,4 +254,12 @@ public class TadoZoneStateAdapter { } return OnOffType.OFF; } + + public State getLight() { + if (zoneState.getSetting().getType() == TadoSystemType.AIR_CONDITIONING) { + Power result = ((CoolingZoneSetting) zoneState.getSetting()).getLight(); + return result != null ? OnOffType.from(result == Power.ON) : UnDefType.NULL; + } + return UnDefType.UNDEF; + } } diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/api/TadoApiTypeUtils.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/api/TadoApiTypeUtils.java index 72d2d3045cc..909648f9b34 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/api/TadoApiTypeUtils.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/api/TadoApiTypeUtils.java @@ -12,9 +12,15 @@ */ package org.openhab.binding.tado.internal.api; +import org.openhab.binding.tado.internal.TadoBindingConstants.FanLevel; import org.openhab.binding.tado.internal.TadoBindingConstants.FanSpeed; +import org.openhab.binding.tado.internal.TadoBindingConstants.HorizontalSwing; import org.openhab.binding.tado.internal.TadoBindingConstants.HvacMode; import org.openhab.binding.tado.internal.TadoBindingConstants.TemperatureUnit; +import org.openhab.binding.tado.internal.TadoBindingConstants.VerticalSwing; +import org.openhab.binding.tado.internal.api.model.ACFanLevel; +import org.openhab.binding.tado.internal.api.model.ACHorizontalSwing; +import org.openhab.binding.tado.internal.api.model.ACVerticalSwing; import org.openhab.binding.tado.internal.api.model.AcFanSpeed; import org.openhab.binding.tado.internal.api.model.AcMode; import org.openhab.binding.tado.internal.api.model.AcModeCapabilities; @@ -144,6 +150,85 @@ public class TadoApiTypeUtils { return null; } + public static ACFanLevel getFanLevel(FanLevel fanLevel) { + if (fanLevel == null) { + return null; + } + + switch (fanLevel) { + case AUTO: + return ACFanLevel.AUTO; + case LEVEL1: + return ACFanLevel.LEVEL1; + case LEVEL2: + return ACFanLevel.LEVEL2; + case LEVEL3: + return ACFanLevel.LEVEL3; + case LEVEL4: + return ACFanLevel.LEVEL4; + case LEVEL5: + return ACFanLevel.LEVEL5; + case SILENT: + return ACFanLevel.SILENT; + } + + return null; + } + + public static ACHorizontalSwing getHorizontalSwing(HorizontalSwing horizontalSwing) { + if (horizontalSwing == null) { + return null; + } + + switch (horizontalSwing) { + case LEFT: + return ACHorizontalSwing.LEFT; + case MID_LEFT: + return ACHorizontalSwing.MID_LEFT; + case MID: + return ACHorizontalSwing.MID; + case MID_RIGHT: + return ACHorizontalSwing.MID_RIGHT; + case RIGHT: + return ACHorizontalSwing.RIGHT; + case ON: + return ACHorizontalSwing.ON; + case OFF: + return ACHorizontalSwing.OFF; + case AUTO: + return ACHorizontalSwing.AUTO; + } + + return null; + } + + public static ACVerticalSwing getVerticalSwing(VerticalSwing verticalSwing) { + if (verticalSwing == null) { + return null; + } + + switch (verticalSwing) { + case AUTO: + return ACVerticalSwing.AUTO; + case UP: + return ACVerticalSwing.UP; + case MID_UP: + return ACVerticalSwing.MID_UP; + case MID: + return ACVerticalSwing.MID; + case MID_DOWN: + return ACVerticalSwing.MID_DOWN; + case DOWN: + return ACVerticalSwing.DOWN; + case ON: + return ACVerticalSwing.ON; + case OFF: + return ACVerticalSwing.OFF; + } + + return null; + } + public static AcModeCapabilities getModeCapabilities(AirConditioningCapabilities capabilities, AcMode mode) { AcModeCapabilities modeCapabilities = null; diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/AirConditioningZoneSettingsBuilder.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/AirConditioningZoneSettingsBuilder.java index 9c0b4d64219..0a5a3c60514 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/AirConditioningZoneSettingsBuilder.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/AirConditioningZoneSettingsBuilder.java @@ -20,6 +20,9 @@ import java.util.List; import org.openhab.binding.tado.internal.TadoBindingConstants.HvacMode; import org.openhab.binding.tado.internal.TadoBindingConstants.TemperatureUnit; import org.openhab.binding.tado.internal.api.ApiException; +import org.openhab.binding.tado.internal.api.model.ACFanLevel; +import org.openhab.binding.tado.internal.api.model.ACHorizontalSwing; +import org.openhab.binding.tado.internal.api.model.ACVerticalSwing; import org.openhab.binding.tado.internal.api.model.AcFanSpeed; import org.openhab.binding.tado.internal.api.model.AcMode; import org.openhab.binding.tado.internal.api.model.AcModeCapabilities; @@ -60,10 +63,26 @@ public class AirConditioningZoneSettingsBuilder extends ZoneSettingsBuilder { setting.setSwing(swing ? Power.ON : Power.OFF); } + if (light != null) { + setting.setLight(light ? Power.ON : Power.OFF); + } + if (fanSpeed != null) { setting.setFanSpeed(getAcFanSpeed(fanSpeed)); } + if (fanLevel != null) { + setting.setFanLevel(getFanLevel(fanLevel)); + } + + if (horizontalSwing != null) { + setting.setHorizontalSwing(getHorizontalSwing(horizontalSwing)); + } + + if (verticalSwing != null) { + setting.setVerticalSwing(getVerticalSwing(verticalSwing)); + } + addMissingSettingParts(zoneStateProvider, genericCapabilities, setting); return setting; @@ -79,21 +98,43 @@ public class AirConditioningZoneSettingsBuilder extends ZoneSettingsBuilder { AcModeCapabilities capabilities = getModeCapabilities((AirConditioningCapabilities) genericCapabilities, setting.getMode()); - if (capabilities.getTemperatures() != null && setting.getTemperature() == null) { - TemperatureObject targetTemperature = getCurrentOrDefaultTemperature(zoneStateProvider, - capabilities.getTemperatures()); - setting.setTemperature(targetTemperature); + TemperatureRange temperatures = capabilities.getTemperatures(); + if (temperatures != null && setting.getTemperature() == null) { + setting.setTemperature(getCurrentOrDefaultTemperature(zoneStateProvider, temperatures)); } - if (capabilities.getFanSpeeds() != null && !capabilities.getFanSpeeds().isEmpty() - && setting.getFanSpeed() == null) { - AcFanSpeed fanSpeed = getCurrentOrDefaultFanSpeed(zoneStateProvider, capabilities.getFanSpeeds()); - setting.setFanSpeed(fanSpeed); + List fanSpeeds = capabilities.getFanSpeeds(); + if (fanSpeeds != null && !fanSpeeds.isEmpty() && setting.getFanSpeed() == null) { + setting.setFanSpeed(getCurrentOrDefaultFanSpeed(zoneStateProvider, fanSpeeds)); } - if (capabilities.getSwings() != null && !capabilities.getSwings().isEmpty() && setting.getSwing() == null) { - Power swing = getCurrentOrDefaultSwing(zoneStateProvider, capabilities.getSwings()); - setting.setSwing(swing); + List swings = capabilities.getSwings(); + if (swings != null && !swings.isEmpty() && setting.getSwing() == null) { + setting.setSwing(getCurrentOrDefaultSwing(zoneStateProvider, swings)); + } + + // Tado confusingly calls the List / getter method 'fanLevel' / 'getFanLevel()' without 's' + List fanLevels = capabilities.getFanLevel(); + if (fanLevels != null && !fanLevels.isEmpty() && setting.getFanLevel() == null) { + setting.setFanLevel(getCurrentOrDefaultFanLevel(zoneStateProvider, fanLevels)); + } + + // Tado confusingly calls the List / getter method 'horizontalSwing' / 'getHorizontalSwing()' without 's' + List horizontalSwings = capabilities.getHorizontalSwing(); + if (horizontalSwings != null && !horizontalSwings.isEmpty() && setting.getHorizontalSwing() == null) { + setting.setHorizontalSwing(getCurrentOrDefaultHorizontalSwing(zoneStateProvider, horizontalSwings)); + } + + // Tado confusingly calls the List / getter method 'verticalSwing' / 'getVerticalSwing()' without 's' + List verticalSwings = capabilities.getVerticalSwing(); + if (verticalSwings != null && !verticalSwings.isEmpty() && setting.getVerticalSwing() == null) { + setting.setVerticalSwing(getCurrentOrDefaultVerticalSwing(zoneStateProvider, verticalSwings)); + } + + // Tado confusingly calls the List / getter method 'light' / 'getLight()' without 's' + List lights = capabilities.getLight(); + if (lights != null && !lights.isEmpty() && setting.getLight() == null) { + setting.setLight(getCurrentOrDefaultLight(zoneStateProvider, lights)); } } @@ -144,6 +185,50 @@ public class AirConditioningZoneSettingsBuilder extends ZoneSettingsBuilder { return swings.get(0); } + private Power getCurrentOrDefaultLight(ZoneStateProvider zoneStateProvider, List lights) + throws IOException, ApiException { + CoolingZoneSetting zoneSetting = (CoolingZoneSetting) zoneStateProvider.getZoneState().getSetting(); + + if (zoneSetting.getLight() != null && lights.contains(zoneSetting.getLight())) { + return zoneSetting.getLight(); + } + + return lights.get(0); + } + + private ACFanLevel getCurrentOrDefaultFanLevel(ZoneStateProvider zoneStateProvider, List fanLevels) + throws IOException, ApiException { + CoolingZoneSetting zoneSetting = (CoolingZoneSetting) zoneStateProvider.getZoneState().getSetting(); + + if (zoneSetting.getFanLevel() != null && fanLevels.contains(zoneSetting.getFanLevel())) { + return zoneSetting.getFanLevel(); + } + + return fanLevels.get(0); + } + + private ACHorizontalSwing getCurrentOrDefaultHorizontalSwing(ZoneStateProvider zoneStateProvider, + List horizontalSwings) throws IOException, ApiException { + CoolingZoneSetting zoneSetting = (CoolingZoneSetting) zoneStateProvider.getZoneState().getSetting(); + + if (zoneSetting.getHorizontalSwing() != null && horizontalSwings.contains(zoneSetting.getHorizontalSwing())) { + return zoneSetting.getHorizontalSwing(); + } + + return horizontalSwings.get(0); + } + + private ACVerticalSwing getCurrentOrDefaultVerticalSwing(ZoneStateProvider zoneStateProvider, + List verticalSwings) throws IOException, ApiException { + CoolingZoneSetting zoneSetting = (CoolingZoneSetting) zoneStateProvider.getZoneState().getSetting(); + + if (zoneSetting.getVerticalSwing() != null && verticalSwings.contains(zoneSetting.getVerticalSwing())) { + return zoneSetting.getVerticalSwing(); + } + + return verticalSwings.get(0); + } + private CoolingZoneSetting coolingSetting(boolean powerOn) { CoolingZoneSetting setting = new CoolingZoneSetting(); setting.setType(TadoSystemType.AIR_CONDITIONING); diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/HeatingZoneSettingsBuilder.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/HeatingZoneSettingsBuilder.java index 13c64d93219..d6d35896571 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/HeatingZoneSettingsBuilder.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/HeatingZoneSettingsBuilder.java @@ -16,8 +16,11 @@ import static org.openhab.binding.tado.internal.api.TadoApiTypeUtils.temperature import java.io.IOException; +import org.openhab.binding.tado.internal.TadoBindingConstants.FanLevel; import org.openhab.binding.tado.internal.TadoBindingConstants.FanSpeed; +import org.openhab.binding.tado.internal.TadoBindingConstants.HorizontalSwing; import org.openhab.binding.tado.internal.TadoBindingConstants.HvacMode; +import org.openhab.binding.tado.internal.TadoBindingConstants.VerticalSwing; import org.openhab.binding.tado.internal.api.ApiException; import org.openhab.binding.tado.internal.api.model.GenericZoneCapabilities; import org.openhab.binding.tado.internal.api.model.GenericZoneSetting; @@ -40,11 +43,31 @@ public class HeatingZoneSettingsBuilder extends ZoneSettingsBuilder { throw new IllegalArgumentException("Heating zones don't support SWING"); } + @Override + public ZoneSettingsBuilder withLight(boolean lightOn) { + throw new IllegalArgumentException("Heating zones don't support LIGHT"); + } + @Override public ZoneSettingsBuilder withFanSpeed(FanSpeed fanSpeed) { throw new IllegalArgumentException("Heating zones don't support FAN SPEED"); } + @Override + public ZoneSettingsBuilder withFanLevel(FanLevel fanLevel) { + throw new IllegalArgumentException("Heating zones don't support FAN LEVEL"); + } + + @Override + public ZoneSettingsBuilder withHorizontalSwing(HorizontalSwing horizontalSwing) { + throw new IllegalArgumentException("Heating zones don't support HORIZONTAL SWING"); + } + + @Override + public ZoneSettingsBuilder withVerticalSwing(VerticalSwing verticalSwing) { + throw new IllegalArgumentException("Heating zones don't support VERTICAL SWING"); + } + @Override public GenericZoneSetting build(ZoneStateProvider zoneStateProvider, GenericZoneCapabilities capabilities) throws IOException, ApiException { diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/HotWaterZoneSettingsBuilder.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/HotWaterZoneSettingsBuilder.java index df3f0e34aee..b4e9d7c77af 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/HotWaterZoneSettingsBuilder.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/HotWaterZoneSettingsBuilder.java @@ -16,8 +16,11 @@ import static org.openhab.binding.tado.internal.api.TadoApiTypeUtils.temperature import java.io.IOException; +import org.openhab.binding.tado.internal.TadoBindingConstants.FanLevel; import org.openhab.binding.tado.internal.TadoBindingConstants.FanSpeed; +import org.openhab.binding.tado.internal.TadoBindingConstants.HorizontalSwing; import org.openhab.binding.tado.internal.TadoBindingConstants.HvacMode; +import org.openhab.binding.tado.internal.TadoBindingConstants.VerticalSwing; import org.openhab.binding.tado.internal.api.ApiException; import org.openhab.binding.tado.internal.api.model.GenericZoneCapabilities; import org.openhab.binding.tado.internal.api.model.GenericZoneSetting; @@ -41,11 +44,31 @@ public class HotWaterZoneSettingsBuilder extends ZoneSettingsBuilder { throw new IllegalArgumentException("Hot Water zones don't support SWING"); } + @Override + public ZoneSettingsBuilder withLight(boolean lightOn) { + throw new IllegalArgumentException("Hot Water zones don't support LIGHT"); + } + @Override public ZoneSettingsBuilder withFanSpeed(FanSpeed fanSpeed) { throw new IllegalArgumentException("Hot Water zones don't support FAN SPEED"); } + @Override + public ZoneSettingsBuilder withFanLevel(FanLevel fanLevel) { + throw new IllegalArgumentException("Hot Water zones don't support FAN LEVEL"); + } + + @Override + public ZoneSettingsBuilder withHorizontalSwing(HorizontalSwing horizontalSwing) { + throw new IllegalArgumentException("Hot Water zones don't support HORIZONTAL SWING"); + } + + @Override + public ZoneSettingsBuilder withVerticalSwing(VerticalSwing verticalSwing) { + throw new IllegalArgumentException("Hot Water zones don't support VERTICAL SWING"); + } + @Override public GenericZoneSetting build(ZoneStateProvider zoneStateProvider, GenericZoneCapabilities capabilities) throws IOException, ApiException { diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/ZoneSettingsBuilder.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/ZoneSettingsBuilder.java index 803c0aa0db1..43d7efd9991 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/ZoneSettingsBuilder.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/ZoneSettingsBuilder.java @@ -15,9 +15,12 @@ package org.openhab.binding.tado.internal.builder; import java.io.IOException; import org.openhab.binding.tado.internal.TadoBindingConstants; +import org.openhab.binding.tado.internal.TadoBindingConstants.FanLevel; import org.openhab.binding.tado.internal.TadoBindingConstants.FanSpeed; +import org.openhab.binding.tado.internal.TadoBindingConstants.HorizontalSwing; import org.openhab.binding.tado.internal.TadoBindingConstants.HvacMode; import org.openhab.binding.tado.internal.TadoBindingConstants.TemperatureUnit; +import org.openhab.binding.tado.internal.TadoBindingConstants.VerticalSwing; import org.openhab.binding.tado.internal.api.ApiException; import org.openhab.binding.tado.internal.api.model.GenericZoneCapabilities; import org.openhab.binding.tado.internal.api.model.GenericZoneSetting; @@ -51,7 +54,11 @@ public abstract class ZoneSettingsBuilder { protected Float temperature = null; protected TemperatureUnit temperatureUnit = TemperatureUnit.CELSIUS; protected Boolean swing = null; + protected Boolean light = null; protected FanSpeed fanSpeed = null; + protected FanLevel fanLevel = null; + protected HorizontalSwing horizontalSwing = null; + protected VerticalSwing verticalSwing = null; public ZoneSettingsBuilder withMode(HvacMode mode) { this.mode = mode; @@ -74,6 +81,21 @@ public abstract class ZoneSettingsBuilder { return this; } + public ZoneSettingsBuilder withFanLevel(FanLevel fanLevel) { + this.fanLevel = fanLevel; + return this; + } + + public ZoneSettingsBuilder withHorizontalSwing(HorizontalSwing horizontalSwing) { + this.horizontalSwing = horizontalSwing; + return this; + } + + public ZoneSettingsBuilder withVerticalSwing(VerticalSwing verticalSwing) { + this.verticalSwing = verticalSwing; + return this; + } + public abstract GenericZoneSetting build(ZoneStateProvider zoneStateProvider, GenericZoneCapabilities capabilities) throws IOException, ApiException; @@ -103,4 +125,9 @@ public abstract class ZoneSettingsBuilder { return temperatureObject; } + + public ZoneSettingsBuilder withLight(boolean lightOn) { + this.light = lightOn; + return this; + } } diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHandlerFactory.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHandlerFactory.java index e6603b4bfa6..f7ac2d6752d 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHandlerFactory.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHandlerFactory.java @@ -32,7 +32,9 @@ import org.openhab.core.thing.binding.BaseThingHandlerFactory; import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandlerFactory; import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link TadoHandlerFactory} is responsible for creating things and thing @@ -48,6 +50,13 @@ public class TadoHandlerFactory extends BaseThingHandlerFactory { private final Map> discoveryServiceRegs = new HashMap<>(); + private final TadoStateDescriptionProvider stateDescriptionProvider; + + @Activate + public TadoHandlerFactory(final @Reference TadoStateDescriptionProvider stateDescriptionProvider) { + this.stateDescriptionProvider = stateDescriptionProvider; + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); @@ -62,7 +71,7 @@ public class TadoHandlerFactory extends BaseThingHandlerFactory { registerTadoDiscoveryService(tadoHomeHandler); return tadoHomeHandler; } else if (thingTypeUID.equals(THING_TYPE_ZONE)) { - return new TadoZoneHandler(thing); + return new TadoZoneHandler(thing, stateDescriptionProvider); } else if (thingTypeUID.equals(THING_TYPE_MOBILE_DEVICE)) { return new TadoMobileDeviceHandler(thing); } diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoStateDescriptionProvider.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoStateDescriptionProvider.java new file mode 100644 index 00000000000..02da72e3072 --- /dev/null +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoStateDescriptionProvider.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2010-2022 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.tado.internal.handler; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.events.EventPublisher; +import org.openhab.core.thing.binding.BaseDynamicStateDescriptionProvider; +import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService; +import org.openhab.core.thing.link.ItemChannelLinkRegistry; +import org.openhab.core.thing.type.DynamicStateDescriptionProvider; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link TadoStateDescriptionProvider} is responsible for providing a dynamic state description of channels whose + * capabilities are not hard coded in the API. + * + * @author Andrew Fiddian-Green - Initial contribution + * + */ +@NonNullByDefault +@Component(service = { DynamicStateDescriptionProvider.class, TadoStateDescriptionProvider.class }) +public class TadoStateDescriptionProvider extends BaseDynamicStateDescriptionProvider { + + @Activate + public TadoStateDescriptionProvider(final @Reference EventPublisher eventPublisher, + final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, + final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) { + this.eventPublisher = eventPublisher; + this.itemChannelLinkRegistry = itemChannelLinkRegistry; + this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService; + } +} diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoZoneHandler.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoZoneHandler.java index 1c035f75da4..e76aa515ead 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoZoneHandler.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoZoneHandler.java @@ -15,24 +15,38 @@ package org.openhab.binding.tado.internal.handler; import static org.openhab.binding.tado.internal.api.TadoApiTypeUtils.terminationConditionTemplateToTerminationCondition; import java.io.IOException; +import java.util.List; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import javax.measure.quantity.Temperature; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.tado.internal.TadoBindingConstants; +import org.openhab.binding.tado.internal.TadoBindingConstants.FanLevel; +import org.openhab.binding.tado.internal.TadoBindingConstants.HorizontalSwing; import org.openhab.binding.tado.internal.TadoBindingConstants.OperationMode; import org.openhab.binding.tado.internal.TadoBindingConstants.TemperatureUnit; +import org.openhab.binding.tado.internal.TadoBindingConstants.VerticalSwing; import org.openhab.binding.tado.internal.TadoBindingConstants.ZoneType; import org.openhab.binding.tado.internal.TadoHvacChange; import org.openhab.binding.tado.internal.adapter.TadoZoneStateAdapter; import org.openhab.binding.tado.internal.api.ApiException; +import org.openhab.binding.tado.internal.api.TadoApiTypeUtils; import org.openhab.binding.tado.internal.api.client.HomeApi; +import org.openhab.binding.tado.internal.api.model.ACFanLevel; +import org.openhab.binding.tado.internal.api.model.ACHorizontalSwing; +import org.openhab.binding.tado.internal.api.model.ACVerticalSwing; +import org.openhab.binding.tado.internal.api.model.AcModeCapabilities; +import org.openhab.binding.tado.internal.api.model.AirConditioningCapabilities; +import org.openhab.binding.tado.internal.api.model.CoolingZoneSetting; import org.openhab.binding.tado.internal.api.model.GenericZoneCapabilities; +import org.openhab.binding.tado.internal.api.model.GenericZoneSetting; import org.openhab.binding.tado.internal.api.model.Overlay; import org.openhab.binding.tado.internal.api.model.OverlayTemplate; import org.openhab.binding.tado.internal.api.model.OverlayTerminationCondition; +import org.openhab.binding.tado.internal.api.model.TadoSystemType; import org.openhab.binding.tado.internal.api.model.Zone; import org.openhab.binding.tado.internal.api.model.ZoneState; import org.openhab.binding.tado.internal.config.TadoZoneConfig; @@ -43,6 +57,7 @@ import org.openhab.core.library.types.StringType; import org.openhab.core.library.unit.ImperialUnits; import org.openhab.core.library.unit.SIUnits; import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; @@ -51,6 +66,7 @@ import org.openhab.core.thing.ThingStatusInfo; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; import org.openhab.core.types.State; +import org.openhab.core.types.StateOption; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,14 +80,17 @@ import org.slf4j.LoggerFactory; public class TadoZoneHandler extends BaseHomeThingHandler { private Logger logger = LoggerFactory.getLogger(TadoZoneHandler.class); + private final TadoStateDescriptionProvider stateDescriptionProvider; + private TadoZoneConfig configuration; private ScheduledFuture refreshTimer; private ScheduledFuture scheduledHvacChange; private GenericZoneCapabilities capabilities; TadoHvacChange pendingHvacChange; - public TadoZoneHandler(Thing thing) { + public TadoZoneHandler(Thing thing, TadoStateDescriptionProvider stateDescriptionProvider) { super(thing); + this.stateDescriptionProvider = stateDescriptionProvider; } public long getZoneId() { @@ -106,7 +125,8 @@ public class TadoZoneHandler extends BaseHomeThingHandler { } public Overlay setOverlay(Overlay overlay) throws IOException, ApiException { - logger.debug("Setting overlay of home {} and zone {}", getHomeId(), getZoneId()); + logger.debug("Setting overlay of home {} and zone {} with overlay: {}", getHomeId(), getZoneId(), + overlay.toString()); return getApi().updateZoneOverlay(getHomeId(), getZoneId(), overlay); } @@ -145,10 +165,28 @@ public class TadoZoneHandler extends BaseHomeThingHandler { pendingHvacChange.withSwing(((OnOffType) command) == OnOffType.ON); scheduleHvacChange(); break; + case TadoBindingConstants.CHANNEL_ZONE_LIGHT: + pendingHvacChange.withLight(((OnOffType) command) == OnOffType.ON); + scheduleHvacChange(); + break; case TadoBindingConstants.CHANNEL_ZONE_FAN_SPEED: pendingHvacChange.withFanSpeed(((StringType) command).toFullString()); scheduleHvacChange(); break; + case TadoBindingConstants.CHANNEL_ZONE_FAN_LEVEL: + String fanLevelString = ((StringType) command).toFullString(); + pendingHvacChange.withFanLevel(FanLevel.valueOf(fanLevelString.toUpperCase())); + break; + case TadoBindingConstants.CHANNEL_ZONE_HORIZONTAL_SWING: + String horizontalSwingString = ((StringType) command).toFullString(); + pendingHvacChange.withHorizontalSwing(HorizontalSwing.valueOf(horizontalSwingString.toUpperCase())); + scheduleHvacChange(); + break; + case TadoBindingConstants.CHANNEL_ZONE_VERTICAL_SWING: + String verticalSwingString = ((StringType) command).toFullString(); + pendingHvacChange.withVerticalSwing(VerticalSwing.valueOf(verticalSwingString.toUpperCase())); + scheduleHvacChange(); + break; case TadoBindingConstants.CHANNEL_ZONE_OPERATION_MODE: String operationMode = ((StringType) command).toFullString(); pendingHvacChange.withOperationMode(OperationMode.valueOf(operationMode)); @@ -206,6 +244,7 @@ public class TadoZoneHandler extends BaseHomeThingHandler { updateProperty(TadoBindingConstants.PROPERTY_ZONE_NAME, zoneDetails.getName()); updateProperty(TadoBindingConstants.PROPERTY_ZONE_TYPE, zoneDetails.getType().name()); this.capabilities = capabilities; + logger.debug("Got capabilities: {}", capabilities.toString()); } catch (IOException | ApiException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Could not connect to server due to " + e.getMessage()); @@ -256,6 +295,10 @@ public class TadoZoneHandler extends BaseHomeThingHandler { updateState(TadoBindingConstants.CHANNEL_ZONE_TARGET_TEMPERATURE, state.getTargetTemperature()); updateState(TadoBindingConstants.CHANNEL_ZONE_FAN_SPEED, state.getFanSpeed()); updateState(TadoBindingConstants.CHANNEL_ZONE_SWING, state.getSwing()); + updateState(TadoBindingConstants.CHANNEL_ZONE_LIGHT, state.getLight()); + updateState(TadoBindingConstants.CHANNEL_ZONE_FAN_LEVEL, state.getFanLevel()); + updateState(TadoBindingConstants.CHANNEL_ZONE_HORIZONTAL_SWING, state.getHorizontalSwing()); + updateState(TadoBindingConstants.CHANNEL_ZONE_VERTICAL_SWING, state.getVerticalSwing()); updateState(TadoBindingConstants.CHANNEL_ZONE_TIMER_DURATION, state.getRemainingTimerDuration()); @@ -263,6 +306,8 @@ public class TadoZoneHandler extends BaseHomeThingHandler { updateState(TadoBindingConstants.CHANNEL_ZONE_OPEN_WINDOW_DETECTED, state.getOpenWindowDetected()); + updateDynamicStateDescriptions(zoneState); + onSuccessfulOperation(); } catch (IOException | ApiException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, @@ -274,6 +319,52 @@ public class TadoZoneHandler extends BaseHomeThingHandler { } } + /** + * Update the dynamic state descriptions for any channels which support an unknown sub- range of enumerator setting + * values, based on the list of capabilities reported by the respective zone. + * + * Note: currently this only applies to A/C devices that support fanLevel, horizontalSwing, or verticalSwing. + * + * @param zoneState the current zone Thing's state + */ + private void updateDynamicStateDescriptions(ZoneState zoneState) { + GenericZoneSetting setting = zoneState.getSetting(); + if (setting.getType() != TadoSystemType.AIR_CONDITIONING) { + return; + } + + AcModeCapabilities acCapabilities = TadoApiTypeUtils.getModeCapabilities( + (AirConditioningCapabilities) capabilities, ((CoolingZoneSetting) setting).getMode()); + + if (acCapabilities != null) { + Channel channel; + + // update the options list of supported fan levels + channel = thing.getChannel(TadoBindingConstants.CHANNEL_ZONE_FAN_LEVEL); + List fanLevels = acCapabilities.getFanLevel(); + if (channel != null && fanLevels != null) { + stateDescriptionProvider.setStateOptions(channel.getUID(), + fanLevels.stream().map(u -> new StateOption(u.name(), u.name())).collect(Collectors.toList())); + } + + // update the options list of supported horizontal swing settings + channel = thing.getChannel(TadoBindingConstants.CHANNEL_ZONE_HORIZONTAL_SWING); + List horizontalSwings = acCapabilities.getHorizontalSwing(); + if (channel != null && horizontalSwings != null) { + stateDescriptionProvider.setStateOptions(channel.getUID(), horizontalSwings.stream() + .map(u -> new StateOption(u.name(), u.name())).collect(Collectors.toList())); + } + + // update the options list of supported vertical swing settings + channel = thing.getChannel(TadoBindingConstants.CHANNEL_ZONE_VERTICAL_SWING); + List verticalSwings = acCapabilities.getVerticalSwing(); + if (channel != null && verticalSwings != null) { + stateDescriptionProvider.setStateOptions(channel.getUID(), verticalSwings.stream() + .map(u -> new StateOption(u.name(), u.name())).collect(Collectors.toList())); + } + } + } + private void scheduleZoneStateUpdate() { if (refreshTimer == null || refreshTimer.isCancelled()) { refreshTimer = scheduler.scheduleWithFixedDelay(new Runnable() { diff --git a/bundles/org.openhab.binding.tado/src/main/resources/OH-INF/i18n/tado.properties b/bundles/org.openhab.binding.tado/src/main/resources/OH-INF/i18n/tado.properties index 887555f05a7..3cf80d0521b 100644 --- a/bundles/org.openhab.binding.tado/src/main/resources/OH-INF/i18n/tado.properties +++ b/bundles/org.openhab.binding.tado/src/main/resources/OH-INF/i18n/tado.properties @@ -41,12 +41,24 @@ channel-type.tado.atHome.label = At Home channel-type.tado.atHome.description = ON if at home, OFF if away channel-type.tado.currentTemperature.label = Temperature channel-type.tado.currentTemperature.description = Current temperature + channel-type.tado.fanspeed.label = Fan Speed channel-type.tado.fanspeed.description = AC fan speed (only if supported by AC) channel-type.tado.fanspeed.state.option.LOW = Low channel-type.tado.fanspeed.state.option.MIDDLE = Middle channel-type.tado.fanspeed.state.option.HIGH = High channel-type.tado.fanspeed.state.option.AUTO = Auto + +channel-type.tado.fanLevel.label = Fan Level +channel-type.tado.fanLevel.description = AC fan speed (only if supported by AC) +channel-type.tado.fanLevel.state.option.SILENT = Silent fan +channel-type.tado.fanLevel.state.option.LEVEL1 = Fan level 1 +channel-type.tado.fanLevel.state.option.LEVEL2 = Fan level 2 +channel-type.tado.fanLevel.state.option.LEVEL3 = Fan level 3 +channel-type.tado.fanLevel.state.option.LEVEL4 = Fan level 4 +channel-type.tado.fanLevel.state.option.LEVEL5 = Fan level 5 +channel-type.tado.fanLevel.state.option.AUTO = Auto fan speed + channel-type.tado.heatingPower.label = Heating Power channel-type.tado.heatingPower.description = Current heating power channel-type.tado.homePresence.label = At Home @@ -74,6 +86,32 @@ channel-type.tado.overlayExpiry.description = Time until when the overlay is act channel-type.tado.overlayExpiry.state.pattern = %1$tF %1$tR channel-type.tado.swing.label = Swing channel-type.tado.swing.description = State of AC swing (only if supported by AC) + +channel-type.tado.light.label = Light +channel-type.tado.light.description = State of control panel light (only if supported by AC) + +channel-type.tado.horizontalSwing.label = Horizontal Swing +channel-type.tado.horizontalSwing.description = State of AC Horizontal swing (only if supported by AC) +channel-type.tado.horizontalSwing.state.option.AUTO = AUTO +channel-type.tado.horizontalSwing.state.option.LEFT = LEFT +channel-type.tado.horizontalSwing.state.option.MID_LEFT = MID-LEFT +channel-type.tado.horizontalSwing.state.option.MID = MID +channel-type.tado.horizontalSwing.state.option.MID_RIGHT = MID-RIGHT +channel-type.tado.horizontalSwing.state.option.RIGHT = RIGHT +channel-type.tado.horizontalSwing.state.option.ON = ON +channel-type.tado.horizontalSwing.state.option.OFF = OFF + +channel-type.tado.verticalSwing.label = Vertical Swing +channel-type.tado.verticalSwing.description = State of AC Vertical swing (only if supported by AC) +channel-type.tado.verticalSwing.state.option.AUTO = AUTO +channel-type.tado.verticalSwing.state.option.UP = UP +channel-type.tado.verticalSwing.state.option.MID_UP = MID-UP +channel-type.tado.verticalSwing.state.option.MID = MID +channel-type.tado.verticalSwing.state.option.MID_DOWN = MID-DOWN +channel-type.tado.verticalSwing.state.option.DOWN = DOWN +channel-type.tado.verticalSwing.state.option.ON = ON +channel-type.tado.verticalSwing.state.option.OFF = OFF + channel-type.tado.targetTemperature.label = Target Temperature channel-type.tado.targetTemperature.description = Thermostat temperature setpoint channel-type.tado.timerDuration.label = Timer Duration diff --git a/bundles/org.openhab.binding.tado/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.tado/src/main/resources/OH-INF/thing/thing-types.xml index d2e17a7fc3d..58c940d21ba 100644 --- a/bundles/org.openhab.binding.tado/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.tado/src/main/resources/OH-INF/thing/thing-types.xml @@ -45,6 +45,10 @@ + + + + @@ -195,6 +199,65 @@ State of AC swing (only if supported by AC) + + Switch + + State of control panel light (only if supported by AC) + + + + String + + AC fan level (only if supported by AC) + + + + + + + + + + + + + + + String + + State of AC horizontal swing (only if supported by AC) + + + + + + + + + + + + + + + + String + + State of AC vertical swing (only if supported by AC) + + + + + + + + + + + + + + String