Add action
attribute to Humidifier entity (#95131)
* Add HumidifierAction StrEnum * Add action attribute to HumidifierEntity * Update strings.json * Add action to demo humidifier * Add tests * Fix imports * Add 'off' humidifier action * Set action to 'off' when state is 'off' * Add 'off' action to strings.json * Test that action sets to "off" when state is "off" * Use is_on instead of state * Fix typo * black
This commit is contained in:
parent
8b6ed9c6b9
commit
ae21ab2945
5 changed files with 44 additions and 0 deletions
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.components.humidifier import (
|
from homeassistant.components.humidifier import (
|
||||||
|
HumidifierAction,
|
||||||
HumidifierDeviceClass,
|
HumidifierDeviceClass,
|
||||||
HumidifierEntity,
|
HumidifierEntity,
|
||||||
HumidifierEntityFeature,
|
HumidifierEntityFeature,
|
||||||
|
@ -30,6 +31,7 @@ async def async_setup_platform(
|
||||||
mode=None,
|
mode=None,
|
||||||
target_humidity=68,
|
target_humidity=68,
|
||||||
current_humidity=45,
|
current_humidity=45,
|
||||||
|
action=HumidifierAction.HUMIDIFYING,
|
||||||
device_class=HumidifierDeviceClass.HUMIDIFIER,
|
device_class=HumidifierDeviceClass.HUMIDIFIER,
|
||||||
),
|
),
|
||||||
DemoHumidifier(
|
DemoHumidifier(
|
||||||
|
@ -37,6 +39,7 @@ async def async_setup_platform(
|
||||||
mode=None,
|
mode=None,
|
||||||
target_humidity=54,
|
target_humidity=54,
|
||||||
current_humidity=59,
|
current_humidity=59,
|
||||||
|
action=HumidifierAction.DRYING,
|
||||||
device_class=HumidifierDeviceClass.DEHUMIDIFIER,
|
device_class=HumidifierDeviceClass.DEHUMIDIFIER,
|
||||||
),
|
),
|
||||||
DemoHumidifier(
|
DemoHumidifier(
|
||||||
|
@ -71,11 +74,13 @@ class DemoHumidifier(HumidifierEntity):
|
||||||
current_humidity: int | None = None,
|
current_humidity: int | None = None,
|
||||||
available_modes: list[str] | None = None,
|
available_modes: list[str] | None = None,
|
||||||
is_on: bool = True,
|
is_on: bool = True,
|
||||||
|
action: HumidifierAction | None = None,
|
||||||
device_class: HumidifierDeviceClass | None = None,
|
device_class: HumidifierDeviceClass | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the humidifier device."""
|
"""Initialize the humidifier device."""
|
||||||
self._attr_name = name
|
self._attr_name = name
|
||||||
self._attr_is_on = is_on
|
self._attr_is_on = is_on
|
||||||
|
self._attr_action = action
|
||||||
self._attr_supported_features = SUPPORT_FLAGS
|
self._attr_supported_features = SUPPORT_FLAGS
|
||||||
if mode is not None:
|
if mode is not None:
|
||||||
self._attr_supported_features |= HumidifierEntityFeature.MODES
|
self._attr_supported_features |= HumidifierEntityFeature.MODES
|
||||||
|
|
|
@ -29,6 +29,7 @@ from homeassistant.helpers.typing import ConfigType
|
||||||
from homeassistant.loader import bind_hass
|
from homeassistant.loader import bind_hass
|
||||||
|
|
||||||
from .const import ( # noqa: F401
|
from .const import ( # noqa: F401
|
||||||
|
ATTR_ACTION,
|
||||||
ATTR_AVAILABLE_MODES,
|
ATTR_AVAILABLE_MODES,
|
||||||
ATTR_CURRENT_HUMIDITY,
|
ATTR_CURRENT_HUMIDITY,
|
||||||
ATTR_HUMIDITY,
|
ATTR_HUMIDITY,
|
||||||
|
@ -45,6 +46,7 @@ from .const import ( # noqa: F401
|
||||||
SERVICE_SET_HUMIDITY,
|
SERVICE_SET_HUMIDITY,
|
||||||
SERVICE_SET_MODE,
|
SERVICE_SET_MODE,
|
||||||
SUPPORT_MODES,
|
SUPPORT_MODES,
|
||||||
|
HumidifierAction,
|
||||||
HumidifierEntityFeature,
|
HumidifierEntityFeature,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -133,6 +135,7 @@ class HumidifierEntity(ToggleEntity):
|
||||||
"""Base class for humidifier entities."""
|
"""Base class for humidifier entities."""
|
||||||
|
|
||||||
entity_description: HumidifierEntityDescription
|
entity_description: HumidifierEntityDescription
|
||||||
|
_attr_action: HumidifierAction | None = None
|
||||||
_attr_available_modes: list[str] | None
|
_attr_available_modes: list[str] | None
|
||||||
_attr_current_humidity: int | None = None
|
_attr_current_humidity: int | None = None
|
||||||
_attr_device_class: HumidifierDeviceClass | None
|
_attr_device_class: HumidifierDeviceClass | None
|
||||||
|
@ -170,6 +173,9 @@ class HumidifierEntity(ToggleEntity):
|
||||||
"""Return the optional state attributes."""
|
"""Return the optional state attributes."""
|
||||||
data: dict[str, int | str | None] = {}
|
data: dict[str, int | str | None] = {}
|
||||||
|
|
||||||
|
if self.action is not None:
|
||||||
|
data[ATTR_ACTION] = self.action if self.is_on else HumidifierAction.OFF
|
||||||
|
|
||||||
if self.current_humidity is not None:
|
if self.current_humidity is not None:
|
||||||
data[ATTR_CURRENT_HUMIDITY] = self.current_humidity
|
data[ATTR_CURRENT_HUMIDITY] = self.current_humidity
|
||||||
|
|
||||||
|
@ -181,6 +187,11 @@ class HumidifierEntity(ToggleEntity):
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@property
|
||||||
|
def action(self) -> HumidifierAction | None:
|
||||||
|
"""Return the current action."""
|
||||||
|
return self._attr_action
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_humidity(self) -> int | None:
|
def current_humidity(self) -> int | None:
|
||||||
"""Return the current humidity."""
|
"""Return the current humidity."""
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
"""Provides the constants needed for component."""
|
"""Provides the constants needed for component."""
|
||||||
from enum import IntFlag
|
from enum import IntFlag
|
||||||
|
|
||||||
|
from homeassistant.backports.enum import StrEnum
|
||||||
|
|
||||||
MODE_NORMAL = "normal"
|
MODE_NORMAL = "normal"
|
||||||
MODE_ECO = "eco"
|
MODE_ECO = "eco"
|
||||||
MODE_AWAY = "away"
|
MODE_AWAY = "away"
|
||||||
|
@ -11,6 +13,17 @@ MODE_SLEEP = "sleep"
|
||||||
MODE_AUTO = "auto"
|
MODE_AUTO = "auto"
|
||||||
MODE_BABY = "baby"
|
MODE_BABY = "baby"
|
||||||
|
|
||||||
|
|
||||||
|
class HumidifierAction(StrEnum):
|
||||||
|
"""Actions for humidifier devices."""
|
||||||
|
|
||||||
|
HUMIDIFYING = "humidifying"
|
||||||
|
DRYING = "drying"
|
||||||
|
IDLE = "idle"
|
||||||
|
OFF = "off"
|
||||||
|
|
||||||
|
|
||||||
|
ATTR_ACTION = "action"
|
||||||
ATTR_AVAILABLE_MODES = "available_modes"
|
ATTR_AVAILABLE_MODES = "available_modes"
|
||||||
ATTR_CURRENT_HUMIDITY = "current_humidity"
|
ATTR_CURRENT_HUMIDITY = "current_humidity"
|
||||||
ATTR_HUMIDITY = "humidity"
|
ATTR_HUMIDITY = "humidity"
|
||||||
|
|
|
@ -28,6 +28,15 @@
|
||||||
"on": "[%key:common::state::on%]"
|
"on": "[%key:common::state::on%]"
|
||||||
},
|
},
|
||||||
"state_attributes": {
|
"state_attributes": {
|
||||||
|
"action": {
|
||||||
|
"name": "Action",
|
||||||
|
"state": {
|
||||||
|
"humidifying": "Humidifying",
|
||||||
|
"drying": "Drying",
|
||||||
|
"idle": "Idle",
|
||||||
|
"off": "Off"
|
||||||
|
}
|
||||||
|
},
|
||||||
"available_modes": {
|
"available_modes": {
|
||||||
"name": "Available modes"
|
"name": "Available modes"
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,7 @@ import pytest
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.humidifier import (
|
from homeassistant.components.humidifier import (
|
||||||
|
ATTR_ACTION,
|
||||||
ATTR_CURRENT_HUMIDITY,
|
ATTR_CURRENT_HUMIDITY,
|
||||||
ATTR_HUMIDITY,
|
ATTR_HUMIDITY,
|
||||||
ATTR_MAX_HUMIDITY,
|
ATTR_MAX_HUMIDITY,
|
||||||
|
@ -45,6 +46,7 @@ def test_setup_params(hass: HomeAssistant) -> None:
|
||||||
assert state.state == STATE_ON
|
assert state.state == STATE_ON
|
||||||
assert state.attributes.get(ATTR_HUMIDITY) == 54
|
assert state.attributes.get(ATTR_HUMIDITY) == 54
|
||||||
assert state.attributes.get(ATTR_CURRENT_HUMIDITY) == 59
|
assert state.attributes.get(ATTR_CURRENT_HUMIDITY) == 59
|
||||||
|
assert state.attributes.get(ATTR_ACTION) == "drying"
|
||||||
|
|
||||||
|
|
||||||
def test_default_setup_params(hass: HomeAssistant) -> None:
|
def test_default_setup_params(hass: HomeAssistant) -> None:
|
||||||
|
@ -124,12 +126,14 @@ async def test_turn_on(hass: HomeAssistant) -> None:
|
||||||
)
|
)
|
||||||
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
||||||
assert state.state == STATE_OFF
|
assert state.state == STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ACTION) == "off"
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: ENTITY_DEHUMIDIFIER}, blocking=True
|
DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: ENTITY_DEHUMIDIFIER}, blocking=True
|
||||||
)
|
)
|
||||||
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
||||||
assert state.state == STATE_ON
|
assert state.state == STATE_ON
|
||||||
|
assert state.attributes.get(ATTR_ACTION) == "drying"
|
||||||
|
|
||||||
|
|
||||||
async def test_turn_off(hass: HomeAssistant) -> None:
|
async def test_turn_off(hass: HomeAssistant) -> None:
|
||||||
|
@ -139,12 +143,14 @@ async def test_turn_off(hass: HomeAssistant) -> None:
|
||||||
)
|
)
|
||||||
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
||||||
assert state.state == STATE_ON
|
assert state.state == STATE_ON
|
||||||
|
assert state.attributes.get(ATTR_ACTION) == "drying"
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: ENTITY_DEHUMIDIFIER}, blocking=True
|
DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: ENTITY_DEHUMIDIFIER}, blocking=True
|
||||||
)
|
)
|
||||||
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
||||||
assert state.state == STATE_OFF
|
assert state.state == STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ACTION) == "off"
|
||||||
|
|
||||||
|
|
||||||
async def test_toggle(hass: HomeAssistant) -> None:
|
async def test_toggle(hass: HomeAssistant) -> None:
|
||||||
|
|
Loading…
Add table
Reference in a new issue