Skip to content

Commit

Permalink
[tado] Add support for fanLevel, verticalSwing, horizontalSwing, ligh…
Browse files Browse the repository at this point in the history
…t API (openhab#12470)

* [tado] fix issue openhab#12160 (first attempt)
* [tado] code style
* [tado] option descriptors
* [tado] add level5
* [tado] fan level and swing not allowed on heating or hot water
* [tado] warn about possible un-supported state values
* [tado] minor formatting
* [tado] harmonise getter methods for fan and swing state
* [tado] include all options in xml
* [tado] remove 's' from capabilities list names (go figure..)
* [tado] add OFF option
* [tado] add support for light channel, and dynamic channel decriptions
* [tado] tweak ReadMe for more clarity
* [tado] adopt reviewer suggestions

Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
  • Loading branch information
andrewfg authored and psmedley committed Feb 23, 2023
1 parent 63cf67e commit 17959c5
Show file tree
Hide file tree
Showing 15 changed files with 700 additions and 34 deletions.
24 changes: 21 additions & 3 deletions bundles/org.openhab.binding.tado/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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`<sup>1)</sup> | String | Fan speed, one of `AUTO`, `LOW`, `MIDDLE`, `HIGH` | RW | `AC`
`fanLevel`<sup>1)</sup> | String | Fan speed, one of <sup>3)</sup> `AUTO`, `SILENT`, `LEVEL1`, `LEVEL2`, `LEVEL3`, `LEVEL4`, `LEVEL5` | RW | `AC`
`swing`<sup>2)</sup> | Switch | Swing on/off | RW | `AC`
`verticalSwing`<sup>2)</sup> | String | Vertical swing state, one of <sup>3)</sup> `OFF`, `ON`, `UP`, `MID_UP`, `MID`, `MID_DOWN`, `DOWN`, `AUTO` | RW | `AC`
`horizontalSwing`<sup>2)</sup> | String | Horizontal swing state, one of <sup>3)</sup> `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`).

<sup>1)</sup> 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.

<sup>2)</sup> 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.

<sup>3)</sup> 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.
Expand Down
74 changes: 72 additions & 2 deletions bundles/org.openhab.binding.tado/src/main/api/tado-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public static enum HvacMode {

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 {
Expand All @@ -74,6 +76,44 @@ public static enum FanSpeed {
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@

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;
Expand Down Expand Up @@ -115,6 +118,21 @@ public TadoHvacChange withFanSpeed(String fanSpeed) {
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();
Expand All @@ -135,4 +153,9 @@ private Overlay buildOverlay() throws IOException, ApiException {

return overlay;
}

public TadoHvacChange withLight(boolean lightOn) {
settingsBuilder.withLight(lightOn);
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
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;
Expand Down Expand Up @@ -119,27 +123,42 @@ public State getTargetTemperature() {

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() {
Expand Down Expand Up @@ -235,4 +254,12 @@ public State getOpenWindowDetected() {
}
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;
}
}
Loading

0 comments on commit 17959c5

Please sign in to comment.