Skip to content

Humidifier

humidifier

humidifier domain implementation.

SPEC module-attribute

SPEC: DomainSpec[Humidifier] = register_domain(DomainSpec(name='humidifier', entity_cls=Humidifier))

The DomainSpec registered with the shared DomainRegistry.

Humidifier

Bases: Entity

A Home Assistant humidifier (or dehumidifier) entity.

The public API uses on() / off() / toggle() as intent-specific names rather than the raw HA turn_on / turn_off services, and exposes humidity-specific state and actions.

Mode operations degrade safely: set_mode checks the entity's reported available_modes and raises ValueError for unsupported modes, while devices that do not report modes at all expose an empty available_modes list and a mode of None.

Source code in src/haclient/domains/humidifier.py
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
class Humidifier(Entity):
    """A Home Assistant humidifier (or dehumidifier) entity.

    The public API uses ``on()`` / ``off()`` / ``toggle()`` as
    intent-specific names rather than the raw HA ``turn_on`` /
    ``turn_off`` services, and exposes humidity-specific state and
    actions.

    Mode operations degrade safely: `set_mode` checks the entity's
    reported `available_modes` and raises ``ValueError`` for unsupported
    modes, while devices that do not report modes at all expose an
    empty `available_modes` list and a `mode` of ``None``.
    """

    domain = "humidifier"

    # -- Listener decorators ------------------------------------------

    def on_turn_on(self, func: ValueChangeHandler) -> ValueChangeHandler:
        """Register a listener for when the humidifier turns on.

        Parameters
        ----------
        func : callable
            Sync or async callable invoked with ``(old_state, new_state)``
            on every transition into the ``on`` state.

        Returns
        -------
        callable
            The same *func*, returned for decorator use.
        """
        return self._register_state_transition_listener("on", func)

    def on_turn_off(self, func: ValueChangeHandler) -> ValueChangeHandler:
        """Register a listener for when the humidifier turns off.

        Parameters
        ----------
        func : callable
            Sync or async callable invoked with ``(old_state, new_state)``
            on every transition into the ``off`` state.

        Returns
        -------
        callable
            The same *func*, returned for decorator use.
        """
        return self._register_state_transition_listener("off", func)

    def on_humidity_change(self, func: ValueChangeHandler) -> ValueChangeHandler:
        """Register a listener for target humidity changes.

        Parameters
        ----------
        func : callable
            Callable invoked with ``(old_value, new_value)`` whenever
            the target ``humidity`` attribute changes.

        Returns
        -------
        callable
            The same *func*, returned for decorator use.
        """
        return self._register_attr_listener("humidity", func)

    def on_mode_change(self, func: ValueChangeHandler) -> ValueChangeHandler:
        """Register a listener for operating mode changes.

        Parameters
        ----------
        func : callable
            Callable invoked with ``(old_value, new_value)`` whenever
            the ``mode`` attribute changes.

        Returns
        -------
        callable
            The same *func*, returned for decorator use.
        """
        return self._register_attr_listener("mode", func)

    # -- State properties ---------------------------------------------

    @property
    def is_on(self) -> bool:
        """Whether the humidifier is currently on."""
        return self.state == "on"

    @property
    def target_humidity(self) -> int | None:
        """Configured target humidity, in percent, if reported."""
        value = self.attributes.get("humidity")
        return int(value) if isinstance(value, (int, float)) else None

    @property
    def current_humidity(self) -> int | None:
        """Currently measured humidity, in percent.

        Returns ``None`` when the device does not report a reading.
        """
        value = self.attributes.get("current_humidity")
        return int(value) if isinstance(value, (int, float)) else None

    @property
    def mode(self) -> str | None:
        """Active operating mode, or ``None`` when the device has none."""
        value = self.attributes.get("mode")
        return str(value) if isinstance(value, str) else None

    @property
    def available_modes(self) -> list[str]:
        """Operating modes supported by the device.

        Returns an empty list when the device does not advertise modes.
        """
        modes = self.attributes.get("available_modes")
        return [str(m) for m in modes] if isinstance(modes, list) else []

    @property
    def device_class(self) -> str | None:
        """Device class (``"humidifier"`` or ``"dehumidifier"``)."""
        value = self.attributes.get("device_class")
        return str(value) if isinstance(value, str) else None

    # -- Actions ------------------------------------------------------

    async def on(self) -> None:
        """Activate the humidifier.

        Invokes the ``humidifier.turn_on`` Home Assistant service.

        Raises
        ------
        CommandError
            If Home Assistant rejects the service call.
        HTTPError
            If the REST call returns a non-2xx response.
        TimeoutError
            If the call exceeds the configured request timeout.
        ConnectionClosedError
            If the WebSocket disconnects mid-call.
        """
        await self._call_service("turn_on")

    async def off(self) -> None:
        """Deactivate the humidifier.

        Invokes the ``humidifier.turn_off`` Home Assistant service.

        Raises
        ------
        CommandError
            If Home Assistant rejects the service call.
        HTTPError
            If the REST call returns a non-2xx response.
        TimeoutError
            If the call exceeds the configured request timeout.
        ConnectionClosedError
            If the WebSocket disconnects mid-call.
        """
        await self._call_service("turn_off")

    async def toggle(self) -> None:
        """Toggle the humidifier state.

        Invokes the ``humidifier.toggle`` Home Assistant service.

        Raises
        ------
        CommandError
            If Home Assistant rejects the service call.
        HTTPError
            If the REST call returns a non-2xx response.
        TimeoutError
            If the call exceeds the configured request timeout.
        ConnectionClosedError
            If the WebSocket disconnects mid-call.
        """
        await self._call_service("toggle")

    async def set_humidity(self, humidity: int) -> None:
        """Set the target humidity, in percent.

        Parameters
        ----------
        humidity : int
            Target humidity between 0 and 100 (inclusive).

        Raises
        ------
        ValueError
            If *humidity* is outside the 0-100 range.
        """
        value = int(humidity)
        if not 0 <= value <= 100:
            raise ValueError("humidity must be between 0 and 100")
        await self._call_service("set_humidity", {"humidity": value})

    async def set_mode(self, mode: str) -> None:
        """Set the operating mode, when supported.

        Parameters
        ----------
        mode : str
            Mode to activate. Must be one of `available_modes` when the
            device reports any; the call is silently skipped for devices
            that do not support modes at all (empty `available_modes`).

        Raises
        ------
        ValueError
            If the device reports `available_modes` and *mode* is not
            in that list.
        """
        modes = self.available_modes
        if not modes:
            # Graceful degradation: device exposes no modes.
            return
        if mode not in modes:
            raise ValueError(
                f"mode {mode!r} not in available_modes {modes!r}",
            )
        await self._call_service("set_mode", {"mode": mode})

is_on property

is_on: bool

Whether the humidifier is currently on.

target_humidity property

target_humidity: int | None

Configured target humidity, in percent, if reported.

current_humidity property

current_humidity: int | None

Currently measured humidity, in percent.

Returns None when the device does not report a reading.

mode property

mode: str | None

Active operating mode, or None when the device has none.

available_modes property

available_modes: list[str]

Operating modes supported by the device.

Returns an empty list when the device does not advertise modes.

device_class property

device_class: str | None

Device class ("humidifier" or "dehumidifier").

on_turn_on

on_turn_on(func: ValueChangeHandler) -> ValueChangeHandler

Register a listener for when the humidifier turns on.

Parameters:

Name Type Description Default
func callable

Sync or async callable invoked with (old_state, new_state) on every transition into the on state.

required

Returns:

Type Description
callable

The same func, returned for decorator use.

Source code in src/haclient/domains/humidifier.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def on_turn_on(self, func: ValueChangeHandler) -> ValueChangeHandler:
    """Register a listener for when the humidifier turns on.

    Parameters
    ----------
    func : callable
        Sync or async callable invoked with ``(old_state, new_state)``
        on every transition into the ``on`` state.

    Returns
    -------
    callable
        The same *func*, returned for decorator use.
    """
    return self._register_state_transition_listener("on", func)

on_turn_off

on_turn_off(func: ValueChangeHandler) -> ValueChangeHandler

Register a listener for when the humidifier turns off.

Parameters:

Name Type Description Default
func callable

Sync or async callable invoked with (old_state, new_state) on every transition into the off state.

required

Returns:

Type Description
callable

The same func, returned for decorator use.

Source code in src/haclient/domains/humidifier.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def on_turn_off(self, func: ValueChangeHandler) -> ValueChangeHandler:
    """Register a listener for when the humidifier turns off.

    Parameters
    ----------
    func : callable
        Sync or async callable invoked with ``(old_state, new_state)``
        on every transition into the ``off`` state.

    Returns
    -------
    callable
        The same *func*, returned for decorator use.
    """
    return self._register_state_transition_listener("off", func)

on_humidity_change

on_humidity_change(func: ValueChangeHandler) -> ValueChangeHandler

Register a listener for target humidity changes.

Parameters:

Name Type Description Default
func callable

Callable invoked with (old_value, new_value) whenever the target humidity attribute changes.

required

Returns:

Type Description
callable

The same func, returned for decorator use.

Source code in src/haclient/domains/humidifier.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
def on_humidity_change(self, func: ValueChangeHandler) -> ValueChangeHandler:
    """Register a listener for target humidity changes.

    Parameters
    ----------
    func : callable
        Callable invoked with ``(old_value, new_value)`` whenever
        the target ``humidity`` attribute changes.

    Returns
    -------
    callable
        The same *func*, returned for decorator use.
    """
    return self._register_attr_listener("humidity", func)

on_mode_change

on_mode_change(func: ValueChangeHandler) -> ValueChangeHandler

Register a listener for operating mode changes.

Parameters:

Name Type Description Default
func callable

Callable invoked with (old_value, new_value) whenever the mode attribute changes.

required

Returns:

Type Description
callable

The same func, returned for decorator use.

Source code in src/haclient/domains/humidifier.py
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
def on_mode_change(self, func: ValueChangeHandler) -> ValueChangeHandler:
    """Register a listener for operating mode changes.

    Parameters
    ----------
    func : callable
        Callable invoked with ``(old_value, new_value)`` whenever
        the ``mode`` attribute changes.

    Returns
    -------
    callable
        The same *func*, returned for decorator use.
    """
    return self._register_attr_listener("mode", func)

on async

on() -> None

Activate the humidifier.

Invokes the humidifier.turn_on Home Assistant service.

Raises:

Type Description
CommandError

If Home Assistant rejects the service call.

HTTPError

If the REST call returns a non-2xx response.

TimeoutError

If the call exceeds the configured request timeout.

ConnectionClosedError

If the WebSocket disconnects mid-call.

Source code in src/haclient/domains/humidifier.py
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
async def on(self) -> None:
    """Activate the humidifier.

    Invokes the ``humidifier.turn_on`` Home Assistant service.

    Raises
    ------
    CommandError
        If Home Assistant rejects the service call.
    HTTPError
        If the REST call returns a non-2xx response.
    TimeoutError
        If the call exceeds the configured request timeout.
    ConnectionClosedError
        If the WebSocket disconnects mid-call.
    """
    await self._call_service("turn_on")

off async

off() -> None

Deactivate the humidifier.

Invokes the humidifier.turn_off Home Assistant service.

Raises:

Type Description
CommandError

If Home Assistant rejects the service call.

HTTPError

If the REST call returns a non-2xx response.

TimeoutError

If the call exceeds the configured request timeout.

ConnectionClosedError

If the WebSocket disconnects mid-call.

Source code in src/haclient/domains/humidifier.py
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
async def off(self) -> None:
    """Deactivate the humidifier.

    Invokes the ``humidifier.turn_off`` Home Assistant service.

    Raises
    ------
    CommandError
        If Home Assistant rejects the service call.
    HTTPError
        If the REST call returns a non-2xx response.
    TimeoutError
        If the call exceeds the configured request timeout.
    ConnectionClosedError
        If the WebSocket disconnects mid-call.
    """
    await self._call_service("turn_off")

toggle async

toggle() -> None

Toggle the humidifier state.

Invokes the humidifier.toggle Home Assistant service.

Raises:

Type Description
CommandError

If Home Assistant rejects the service call.

HTTPError

If the REST call returns a non-2xx response.

TimeoutError

If the call exceeds the configured request timeout.

ConnectionClosedError

If the WebSocket disconnects mid-call.

Source code in src/haclient/domains/humidifier.py
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
async def toggle(self) -> None:
    """Toggle the humidifier state.

    Invokes the ``humidifier.toggle`` Home Assistant service.

    Raises
    ------
    CommandError
        If Home Assistant rejects the service call.
    HTTPError
        If the REST call returns a non-2xx response.
    TimeoutError
        If the call exceeds the configured request timeout.
    ConnectionClosedError
        If the WebSocket disconnects mid-call.
    """
    await self._call_service("toggle")

set_humidity async

set_humidity(humidity: int) -> None

Set the target humidity, in percent.

Parameters:

Name Type Description Default
humidity int

Target humidity between 0 and 100 (inclusive).

required

Raises:

Type Description
ValueError

If humidity is outside the 0-100 range.

Source code in src/haclient/domains/humidifier.py
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
async def set_humidity(self, humidity: int) -> None:
    """Set the target humidity, in percent.

    Parameters
    ----------
    humidity : int
        Target humidity between 0 and 100 (inclusive).

    Raises
    ------
    ValueError
        If *humidity* is outside the 0-100 range.
    """
    value = int(humidity)
    if not 0 <= value <= 100:
        raise ValueError("humidity must be between 0 and 100")
    await self._call_service("set_humidity", {"humidity": value})

set_mode async

set_mode(mode: str) -> None

Set the operating mode, when supported.

Parameters:

Name Type Description Default
mode str

Mode to activate. Must be one of available_modes when the device reports any; the call is silently skipped for devices that do not support modes at all (empty available_modes).

required

Raises:

Type Description
ValueError

If the device reports available_modes and mode is not in that list.

Source code in src/haclient/domains/humidifier.py
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
async def set_mode(self, mode: str) -> None:
    """Set the operating mode, when supported.

    Parameters
    ----------
    mode : str
        Mode to activate. Must be one of `available_modes` when the
        device reports any; the call is silently skipped for devices
        that do not support modes at all (empty `available_modes`).

    Raises
    ------
    ValueError
        If the device reports `available_modes` and *mode* is not
        in that list.
    """
    modes = self.available_modes
    if not modes:
        # Graceful degradation: device exposes no modes.
        return
    if mode not in modes:
        raise ValueError(
            f"mode {mode!r} not in available_modes {modes!r}",
        )
    await self._call_service("set_mode", {"mode": mode})