From 5c04d2085a17674b0ada9b552f45e7fa18b46327 Mon Sep 17 00:00:00 2001 From: G Johansson Date: Wed, 4 Dec 2024 11:45:05 +0100 Subject: [PATCH] Update ClimateEntity for horizontal swing support (#2309) --- blog/2024-12-03-climate-horizontal-swing.md | 73 +++++++++++++++++++++ docs/core/entity/climate.md | 39 ++++++++++- 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 blog/2024-12-03-climate-horizontal-swing.md diff --git a/blog/2024-12-03-climate-horizontal-swing.md b/blog/2024-12-03-climate-horizontal-swing.md new file mode 100644 index 00000000..27a72cf5 --- /dev/null +++ b/blog/2024-12-03-climate-horizontal-swing.md @@ -0,0 +1,73 @@ +--- +author: G Johansson +authorURL: https://github.com/gjohansson-ST +authorImageURL: https://avatars.githubusercontent.com/u/62932417?v=4 +authorTwitter: GJohansson +title: "Climate entity now supports independent horizontal swing" +--- + +As of Home Assistant Core 2024.12, we have implemented an independent property and method for controlling horizontal swing in `ClimateEntity`. + +Integrations that support completely independent control and state for vertical and horizontal swing can now use the previous `swing_mode` for vertical swing only and use the new `swing_horizontal_mode` for providing the horizontal swing state and control. + +Integrations that don't have independent control should still keep using the current `swing_mode` for both vertical and horizontal support. + + +### Example + +Example requirements to implement `swing` and `swing_horizontal` in your climate entity. + +```python + +class MyClimateEntity(ClimateEntity): + """Implementation of my climate entity.""" + + @property + def supported_features(self) -> ClimateEntityFeature: + """Return the list of supported features.""" + return ClimateEntityFeature.SWING_MODE | ClimateEntityFeature.SWING_HORIZONTAL_MODE + + @property + def swing_mode(self) -> str | None: + """Return the swing setting. + + Requires ClimateEntityFeature.SWING_MODE. + """ + return self._attr_swing_mode + + @property + def swing_modes(self) -> list[str] | None: + """Return the list of available swing modes. + + Requires ClimateEntityFeature.SWING_MODE. + """ + return self._attr_swing_modes + + @property + def swing_horizontal_mode(self) -> str | None: + """Return the swing setting. + + Requires ClimateEntityFeature.SWING_HORIZONTAL_MODE. + """ + return self._attr_swing_horizontal_mode + + @property + def swing_horizontal_modes(self) -> list[str] | None: + """Return the list of available swing modes. + + Requires ClimateEntityFeature.SWING_HORIZONTAL_MODE. + """ + return self._attr_swing_horizontal_modes + + async def async_set_swing_mode(self, swing_mode: str) -> None: + """Set new target swing operation.""" + await self.api.set_swing_mode(swing_mode) + + async def async_set_swing_horizontal_mode(self, swing_horizontal_mode: str) -> None: + """Set new target horizontal swing operation.""" + await self.api.set_swing_horizontal_mode(swing_horizontal_mode) + +``` + +More details can be found in the [climate documentation](/docs/core/entity/climate#swing-modes). + diff --git a/docs/core/entity/climate.md b/docs/core/entity/climate.md index f6172b23..597e19f2 100644 --- a/docs/core/entity/climate.md +++ b/docs/core/entity/climate.md @@ -28,7 +28,9 @@ Properties should always only return information from memory and not do I/O (lik | preset_mode | str | None | **Required by SUPPORT_PRESET_MODE** | The current active preset. | | preset_modes | list[str] | None | **Required by SUPPORT_PRESET_MODE** | The available presets. | | swing_mode | str | None | **Required by SUPPORT_SWING_MODE** | The swing setting. | -| swing_modes | list[str] | None | **Required by SUPPORT_SWING_MODE** | Returns the list of available swing modes. | +| swing_modes | list[str] | None | **Required by SUPPORT_SWING_MODE** | Returns the list of available swing modes, only vertical modes in the case horizontal swing is implemented. | +| swing_horizontal_mode | str | None | **Required by SUPPORT_SWING_HORIZONTAL_MODE** | The horizontal swing setting. | +| swing_horizontal_modes | list[str] | None | **Required by SUPPORT_SWING_HORIZONTAL_MODE** | Returns the list of available horizontal swing modes. | | target_humidity | float | None | `None` | The target humidity the device is trying to reach. | | target_temperature | float | None | `None` | The temperature currently set to be reached. | | target_temperature_high | float | None | **Required by TARGET_TEMPERATURE_RANGE** | The upper bound target temperature | @@ -102,6 +104,12 @@ A device's fan can have different states. There are a couple of built-in fan mod The device fan can have different swing modes that it wants the user to know about/control. +:::note + +For integrations that don't have independent control of vertical and horizontal swing, all possible options should be listed in `swing_modes`, otherwise `swing_modes` provides vertical support and `swing_horizontal_modes` should provide horizontal support. + +::: + | Name | Description | | ------------------ | ------------------------------------------------- | | `SWING_OFF` | The fan is not swinging. | @@ -110,6 +118,21 @@ The device fan can have different swing modes that it wants the user to know abo | `SWING_HORIZONTAL` | The fan is swinging horizontal. | | `SWING_BOTH` | The fan is swinging both horizontal and vertical. | +### Swing horizontal modes + +The device fan can have different horizontal swing modes that it wants the user to know about/control. + +:::note + +This should only be implemented if the integration has independent control of vertical and horizontal swing. In such case the `swing_modes` property will provide vertical support and `swing_horizontal_modes` will provide horizontal support. + +::: + +| Name | Description | +| ------------------ | ------------------------------------------------- | +| `SWING_OFF` | The fan is not swinging. | +| `SWING_ON` | The fan is swinging. | + ## Supported features Supported features are defined by using values in the `ClimateEntityFeature` enum @@ -123,6 +146,7 @@ and are combined using the bitwise or (`|`) operator. | `FAN_MODE` | The device supports fan modes. | | `PRESET_MODE` | The device supports presets. | | `SWING_MODE` | The device supports swing modes. | +| `SWING_HORIZONTAL_MODE` | The device supports horizontal swing modes. | | `TURN_ON` | The device supports turn on. | | `TURN_OFF` | The device supports turn off. | @@ -243,6 +267,19 @@ class MyClimateEntity(ClimateEntity): """Set new target swing operation.""" ``` +### Set horizontal swing mode + +```python +class MyClimateEntity(ClimateEntity): + # Implement one of these methods. + + def set_swing_horizontal_mode(self, swing_mode): + """Set new target horizontal swing operation.""" + + async def async_set_swing_horizontal_mode(self, swing_mode): + """Set new target horizontal swing operation.""" +``` + ### Set temperature :::note