Skip to content

Light

light

light domain implementation.

SPEC module-attribute

SPEC: DomainSpec[Light] = register_domain(DomainSpec(name='light', entity_cls=Light))

The DomainSpec registered with the shared DomainRegistry.

Light

Bases: Entity

A Home Assistant light entity.

Provides intent-specific methods for controlling brightness, color, and color temperature rather than exposing the overloaded turn_on / turn_off HA service interface directly.

Properties expose the current state of the light: whether it is on, its brightness, RGB color, and Kelvin color temperature.

Source code in src/haclient/domains/light.py
 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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
class Light(Entity):
    """A Home Assistant light entity.

    Provides intent-specific methods for controlling brightness, color,
    and color temperature rather than exposing the overloaded
    ``turn_on`` / ``turn_off`` HA service interface directly.

    Properties expose the current state of the light: whether it is on,
    its brightness, RGB color, and Kelvin color temperature.
    """

    domain = "light"

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

    def on_turn_on(self, func: ValueChangeHandler) -> ValueChangeHandler:
        """Register a listener for when the light 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 light 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_brightness_change(self, func: ValueChangeHandler) -> ValueChangeHandler:
        """Register a listener for brightness changes.

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

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

    def on_color_change(self, func: ValueChangeHandler) -> ValueChangeHandler:
        """Register a listener for RGB color changes.

        Parameters
        ----------
        func : callable
            Callable invoked with ``(old_value, new_value)`` whenever
            the ``rgb_color`` attribute reported by Home Assistant
            changes.

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

    def on_kelvin_change(self, func: ValueChangeHandler) -> ValueChangeHandler:
        """Register a listener for color temperature (Kelvin) changes.

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

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

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

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

    @property
    def brightness(self) -> int | None:
        """Current brightness (0--255) or ``None``."""
        value = self.attributes.get("brightness")
        return int(value) if isinstance(value, (int, float)) else None

    @property
    def min_kelvin(self) -> int | None:
        """Minimum supported color temperature in Kelvin, or ``None``."""
        value = self.attributes.get("min_color_temp_kelvin")
        return int(value) if isinstance(value, (int, float)) else None

    @property
    def max_kelvin(self) -> int | None:
        """Maximum supported color temperature in Kelvin, or ``None``."""
        value = self.attributes.get("max_color_temp_kelvin")
        return int(value) if isinstance(value, (int, float)) else None

    @property
    def kelvin(self) -> int | None:
        """Current color temperature in Kelvin, or ``None``."""
        value = self.attributes.get("color_temp_kelvin")
        return int(value) if isinstance(value, (int, float)) else None

    @property
    def rgb_color(self) -> tuple[int, int, int] | None:
        """Current RGB color tuple.

        Returns
        -------
        tuple of int or None
            Three-tuple ``(r, g, b)`` with each component coerced to
            ``int`` in the range 0--255. ``None`` when the underlying
            ``rgb_color`` attribute is missing or is not a 3-element
            sequence.
        """
        value = self.attributes.get("rgb_color")
        if isinstance(value, (list, tuple)) and len(value) == 3:
            return (int(value[0]), int(value[1]), int(value[2]))
        return None

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

    async def set_brightness(self, brightness: int, *, transition: float | None = None) -> None:
        """Set the brightness (0--255), turning the light on if needed.

        Parameters
        ----------
        brightness : int
            New brightness value in the range 0--255. ``0`` turns the
            light off; ``255`` is full brightness.
        transition : float or None, optional
            Seconds for the transition. Forwarded to HA when set.

        Raises
        ------
        ValueError
            If *brightness* is outside the 0--255 range.
        """
        data: dict[str, Any] = {"brightness": validate_range(brightness, 0, 255, "brightness")}
        if transition is not None:
            data["transition"] = transition
        await self._call_service("turn_on", data)

    async def set_kelvin(self, kelvin: int, *, transition: float | None = None) -> None:
        """Set the color temperature in Kelvin, turning the light on if needed.

        Parameters
        ----------
        kelvin : int
            Target color temperature in Kelvin.
        transition : float or None, optional
            Seconds for the transition. Forwarded to HA when set.

        Raises
        ------
        TypeError
            If *kelvin* cannot be coerced to ``int``.
        ValueError
            If *kelvin* cannot be coerced to ``int`` (e.g. a non-numeric
            string).

        Notes
        -----
        The value is forwarded to Home Assistant verbatim; this method
        does **not** clamp against `min_kelvin` / `max_kelvin`. Values
        outside the device's supported range will surface as
        `CommandError` from Home Assistant.
        """
        data: dict[str, Any] = {"color_temp_kelvin": int(kelvin)}
        if transition is not None:
            data["transition"] = transition
        await self._call_service("turn_on", data)

    async def set_rgb(
        self,
        r: int,
        g: int,
        b: int,
        *,
        transition: float | None = None,
    ) -> None:
        """Set the RGB color, turning the light on if needed.

        Parameters
        ----------
        r : int
            Red component (0--255).
        g : int
            Green component (0--255).
        b : int
            Blue component (0--255).
        transition : float or None, optional
            Seconds for the transition. Forwarded to HA when set.

        Raises
        ------
        ValueError
            If any component is outside the 0--255 range.
        """
        rgb = [
            validate_range(r, 0, 255, "r"),
            validate_range(g, 0, 255, "g"),
            validate_range(b, 0, 255, "b"),
        ]
        data: dict[str, Any] = {"rgb_color": rgb}
        if transition is not None:
            data["transition"] = transition
        await self._call_service("turn_on", data)

    async def set_color(
        self,
        *,
        rgb: tuple[int, int, int] | None = None,
        kelvin: int | None = None,
        transition: float | None = None,
    ) -> None:
        """Set the light color by RGB or Kelvin.

        Exactly one of *rgb* or *kelvin* must be provided.

        Parameters
        ----------
        rgb : tuple of int or None, optional
            Three-tuple ``(r, g, b)`` with components in 0-255.
        kelvin : int or None, optional
            Target color temperature in Kelvin.
        transition : float or None, optional
            Seconds for the transition. Forwarded to HA when set.

        Raises
        ------
        ValueError
            If neither or both of *rgb* and *kelvin* are provided.
        """
        if (rgb is None) == (kelvin is None):
            raise ValueError("Exactly one of 'rgb' or 'kelvin' must be provided")
        if rgb is not None:
            data: dict[str, Any] = {"rgb_color": list(rgb)}
            if transition is not None:
                data["transition"] = transition
            await self._call_service("turn_on", data)
        else:
            data = {"color_temp_kelvin": int(kelvin)}  # type: ignore[arg-type]
            if transition is not None:
                data["transition"] = transition
            await self._call_service("turn_on", data)

    async def on(self, *, transition: float | None = None) -> None:
        """Turn the light on without changing color or brightness.

        Parameters
        ----------
        transition : float or None, optional
            Seconds for the transition. Forwarded to HA when set.
        """
        data: dict[str, Any] = {}
        if transition is not None:
            data["transition"] = transition
        await self._call_service("turn_on", data or None)

    async def off(self, *, transition: float | None = None) -> None:
        """Turn the light off.

        Parameters
        ----------
        transition : float or None, optional
            Seconds for the transition. Forwarded to HA when set.
        """
        data: dict[str, Any] = {}
        if transition is not None:
            data["transition"] = transition
        await self._call_service("turn_off", data or None)

    async def toggle(self) -> None:
        """Toggle the on/off state of the light."""
        await self._call_service("toggle")

is_on property

is_on: bool

Whether the light is currently on.

brightness property

brightness: int | None

Current brightness (0--255) or None.

min_kelvin property

min_kelvin: int | None

Minimum supported color temperature in Kelvin, or None.

max_kelvin property

max_kelvin: int | None

Maximum supported color temperature in Kelvin, or None.

kelvin property

kelvin: int | None

Current color temperature in Kelvin, or None.

rgb_color property

rgb_color: tuple[int, int, int] | None

Current RGB color tuple.

Returns:

Type Description
tuple of int or None

Three-tuple (r, g, b) with each component coerced to int in the range 0--255. None when the underlying rgb_color attribute is missing or is not a 3-element sequence.

on_turn_on

on_turn_on(func: ValueChangeHandler) -> ValueChangeHandler

Register a listener for when the light 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/light.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 light 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 light 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/light.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 light 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_brightness_change

on_brightness_change(func: ValueChangeHandler) -> ValueChangeHandler

Register a listener for brightness changes.

Parameters:

Name Type Description Default
func callable

Callable invoked with (old_value, new_value) whenever the brightness attribute (0-255) changes.

required

Returns:

Type Description
callable

The same func, returned for decorator use.

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

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

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

on_color_change

on_color_change(func: ValueChangeHandler) -> ValueChangeHandler

Register a listener for RGB color changes.

Parameters:

Name Type Description Default
func callable

Callable invoked with (old_value, new_value) whenever the rgb_color attribute reported by Home Assistant changes.

required

Returns:

Type Description
callable

The same func, returned for decorator use.

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

    Parameters
    ----------
    func : callable
        Callable invoked with ``(old_value, new_value)`` whenever
        the ``rgb_color`` attribute reported by Home Assistant
        changes.

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

on_kelvin_change

on_kelvin_change(func: ValueChangeHandler) -> ValueChangeHandler

Register a listener for color temperature (Kelvin) changes.

Parameters:

Name Type Description Default
func callable

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

required

Returns:

Type Description
callable

The same func, returned for decorator use.

Source code in src/haclient/domains/light.py
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
def on_kelvin_change(self, func: ValueChangeHandler) -> ValueChangeHandler:
    """Register a listener for color temperature (Kelvin) changes.

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

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

set_brightness async

set_brightness(brightness: int, *, transition: float | None = None) -> None

Set the brightness (0--255), turning the light on if needed.

Parameters:

Name Type Description Default
brightness int

New brightness value in the range 0--255. 0 turns the light off; 255 is full brightness.

required
transition float or None

Seconds for the transition. Forwarded to HA when set.

None

Raises:

Type Description
ValueError

If brightness is outside the 0--255 range.

Source code in src/haclient/domains/light.py
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
async def set_brightness(self, brightness: int, *, transition: float | None = None) -> None:
    """Set the brightness (0--255), turning the light on if needed.

    Parameters
    ----------
    brightness : int
        New brightness value in the range 0--255. ``0`` turns the
        light off; ``255`` is full brightness.
    transition : float or None, optional
        Seconds for the transition. Forwarded to HA when set.

    Raises
    ------
    ValueError
        If *brightness* is outside the 0--255 range.
    """
    data: dict[str, Any] = {"brightness": validate_range(brightness, 0, 255, "brightness")}
    if transition is not None:
        data["transition"] = transition
    await self._call_service("turn_on", data)

set_kelvin async

set_kelvin(kelvin: int, *, transition: float | None = None) -> None

Set the color temperature in Kelvin, turning the light on if needed.

Parameters:

Name Type Description Default
kelvin int

Target color temperature in Kelvin.

required
transition float or None

Seconds for the transition. Forwarded to HA when set.

None

Raises:

Type Description
TypeError

If kelvin cannot be coerced to int.

ValueError

If kelvin cannot be coerced to int (e.g. a non-numeric string).

Notes

The value is forwarded to Home Assistant verbatim; this method does not clamp against min_kelvin / max_kelvin. Values outside the device's supported range will surface as CommandError from Home Assistant.

Source code in src/haclient/domains/light.py
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
async def set_kelvin(self, kelvin: int, *, transition: float | None = None) -> None:
    """Set the color temperature in Kelvin, turning the light on if needed.

    Parameters
    ----------
    kelvin : int
        Target color temperature in Kelvin.
    transition : float or None, optional
        Seconds for the transition. Forwarded to HA when set.

    Raises
    ------
    TypeError
        If *kelvin* cannot be coerced to ``int``.
    ValueError
        If *kelvin* cannot be coerced to ``int`` (e.g. a non-numeric
        string).

    Notes
    -----
    The value is forwarded to Home Assistant verbatim; this method
    does **not** clamp against `min_kelvin` / `max_kelvin`. Values
    outside the device's supported range will surface as
    `CommandError` from Home Assistant.
    """
    data: dict[str, Any] = {"color_temp_kelvin": int(kelvin)}
    if transition is not None:
        data["transition"] = transition
    await self._call_service("turn_on", data)

set_rgb async

set_rgb(r: int, g: int, b: int, *, transition: float | None = None) -> None

Set the RGB color, turning the light on if needed.

Parameters:

Name Type Description Default
r int

Red component (0--255).

required
g int

Green component (0--255).

required
b int

Blue component (0--255).

required
transition float or None

Seconds for the transition. Forwarded to HA when set.

None

Raises:

Type Description
ValueError

If any component is outside the 0--255 range.

Source code in src/haclient/domains/light.py
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
async def set_rgb(
    self,
    r: int,
    g: int,
    b: int,
    *,
    transition: float | None = None,
) -> None:
    """Set the RGB color, turning the light on if needed.

    Parameters
    ----------
    r : int
        Red component (0--255).
    g : int
        Green component (0--255).
    b : int
        Blue component (0--255).
    transition : float or None, optional
        Seconds for the transition. Forwarded to HA when set.

    Raises
    ------
    ValueError
        If any component is outside the 0--255 range.
    """
    rgb = [
        validate_range(r, 0, 255, "r"),
        validate_range(g, 0, 255, "g"),
        validate_range(b, 0, 255, "b"),
    ]
    data: dict[str, Any] = {"rgb_color": rgb}
    if transition is not None:
        data["transition"] = transition
    await self._call_service("turn_on", data)

set_color async

set_color(*, rgb: tuple[int, int, int] | None = None, kelvin: int | None = None, transition: float | None = None) -> None

Set the light color by RGB or Kelvin.

Exactly one of rgb or kelvin must be provided.

Parameters:

Name Type Description Default
rgb tuple of int or None

Three-tuple (r, g, b) with components in 0-255.

None
kelvin int or None

Target color temperature in Kelvin.

None
transition float or None

Seconds for the transition. Forwarded to HA when set.

None

Raises:

Type Description
ValueError

If neither or both of rgb and kelvin are provided.

Source code in src/haclient/domains/light.py
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
async def set_color(
    self,
    *,
    rgb: tuple[int, int, int] | None = None,
    kelvin: int | None = None,
    transition: float | None = None,
) -> None:
    """Set the light color by RGB or Kelvin.

    Exactly one of *rgb* or *kelvin* must be provided.

    Parameters
    ----------
    rgb : tuple of int or None, optional
        Three-tuple ``(r, g, b)`` with components in 0-255.
    kelvin : int or None, optional
        Target color temperature in Kelvin.
    transition : float or None, optional
        Seconds for the transition. Forwarded to HA when set.

    Raises
    ------
    ValueError
        If neither or both of *rgb* and *kelvin* are provided.
    """
    if (rgb is None) == (kelvin is None):
        raise ValueError("Exactly one of 'rgb' or 'kelvin' must be provided")
    if rgb is not None:
        data: dict[str, Any] = {"rgb_color": list(rgb)}
        if transition is not None:
            data["transition"] = transition
        await self._call_service("turn_on", data)
    else:
        data = {"color_temp_kelvin": int(kelvin)}  # type: ignore[arg-type]
        if transition is not None:
            data["transition"] = transition
        await self._call_service("turn_on", data)

on async

on(*, transition: float | None = None) -> None

Turn the light on without changing color or brightness.

Parameters:

Name Type Description Default
transition float or None

Seconds for the transition. Forwarded to HA when set.

None
Source code in src/haclient/domains/light.py
283
284
285
286
287
288
289
290
291
292
293
294
async def on(self, *, transition: float | None = None) -> None:
    """Turn the light on without changing color or brightness.

    Parameters
    ----------
    transition : float or None, optional
        Seconds for the transition. Forwarded to HA when set.
    """
    data: dict[str, Any] = {}
    if transition is not None:
        data["transition"] = transition
    await self._call_service("turn_on", data or None)

off async

off(*, transition: float | None = None) -> None

Turn the light off.

Parameters:

Name Type Description Default
transition float or None

Seconds for the transition. Forwarded to HA when set.

None
Source code in src/haclient/domains/light.py
296
297
298
299
300
301
302
303
304
305
306
307
async def off(self, *, transition: float | None = None) -> None:
    """Turn the light off.

    Parameters
    ----------
    transition : float or None, optional
        Seconds for the transition. Forwarded to HA when set.
    """
    data: dict[str, Any] = {}
    if transition is not None:
        data["transition"] = transition
    await self._call_service("turn_off", data or None)

toggle async

toggle() -> None

Toggle the on/off state of the light.

Source code in src/haclient/domains/light.py
309
310
311
async def toggle(self) -> None:
    """Toggle the on/off state of the light."""
    await self._call_service("toggle")