core icon indicating copy to clipboard operation
core copied to clipboard

Setting color temperature when bulb is off does not work

Open djurny opened this issue 1 year ago • 12 comments

The problem

Summary

When setting color temperature of a bulb that is off, it seems that color temperature value is not sent. Bulb used is a (set of) Ikea E26 1100lm bulbs. Zigbee2MQTT is used to talk to the bulbs.

How to reproduce the issue

  1. Turn on the light
  2. Check current color temperature color temp is 286 according to Z2M frontend
  3. Turn OFF the light
  4. Change color temperature to 454 using Z2M frontend
  5. Change color temperature to 286 using light.turn_on with brightness = 0 Z2M log shows: info 2024-07-05 18:49:13MQTT publish: topic 'zigbee2mqtt/Bulb IKEA E26 1100lm No.11', payload '{"brightness":1,"color_mode":"color_temp","color_options":{"execute_if_off":true},"color_temp":454,"last_seen":"2024-07-05T18:49:13-07:00","level_config":{"on_level":"previous"},"linkquality":39,"power_on_behavior":null,"state":"OFF","update":{"installed_version":65554,"latest_version":65554,"state":"idle"},"update_available":null}'
  6. Refresh color temperature in Z2M frontend: still set to 454, light.turn_on did not have any effect.
  7. Turn on the light
  8. Observe color temperature not changing when turning on the bulb (still at 454 as set at previous step) It appears that color_temp (nor kelvin) is not sent to Zigbee2MQTT when brightness = 0 by light.turn_on.

What version of Home Assistant Core has the issue?

core-2024.7.0

What was the last working version of Home Assistant Core?

No response

What type of installation are you running?

Home Assistant Container

Integration causing the issue

No response

Link to integration documentation on our website

No response

Diagnostics information

No response

Example YAML snippet

No response

Anything in the logs that might be useful for us?

No response

Additional information

Z2M execute if off is enabled in color options. Function seems to do what it says when using the Z2M frontend to change color temperature while bulb is off.

djurny avatar Jul 06 '24 03:07 djurny

Workaround based on this comment: Add an mqtt.publish message to enable execute_if_off and mqtt.publish a message to set the color_temp wanted before the light is turned on.

//snip
        - repeat:
            for_each: '{{ state_attr(entity_light, "entity_id") }}'
            sequence:
            - service: mqtt.publish
              data_template:
                topic: 'zigbee2mqtt/{{state_attr(repeat.item, "friendly_name")}}/set/color_options'
                payload: |
                  {
                    "execute_if_off": "true"
                  }
            - service: mqtt.publish
              data_template:
                topic: 'zigbee2mqtt/{{state_attr(repeat.item, "friendly_name")}}/set'
                payload: |
                  {
                    "color_temp": "{{turn_on_quirk_color_temp_mired_current}}",
                    "transition": "0"
                  }
//snip

This workaround will only work when using Zigbee lights + zigbee2mqtt. In my case, the Philips Hue and Ikea bulbs luckily support the execute_if_off feature for setting the color temperature.

Related issues:

  • https://github.com/Koenkk/zigbee2mqtt/discussions/13156#discussioncomment-4491986
  • https://github.com/basnijholt/adaptive-lighting/issues/1022#issue-2393247901

djurny avatar Jul 09 '24 22:07 djurny

Workaround based on this comment: Add an mqtt.publish message to enable execute_if_off and mqtt.publish a message to set the color_temp wanted before the light is turned on.

//snip
        - repeat:
            for_each: '{{ state_attr(entity_light, "entity_id") }}'
            sequence:
            - service: mqtt.publish
              data_template:
                topic: 'zigbee2mqtt/{{state_attr(repeat.item, "friendly_name")}}/set/color_options'
                payload: |
                  {
                    "execute_if_off": "true"
                  }
            - service: mqtt.publish
              data_template:
                topic: 'zigbee2mqtt/{{state_attr(repeat.item, "friendly_name")}}/set'
                payload: |
                  {
                    "color_temp": "{{turn_on_quirk_color_temp_mired_current}}",
                    "transition": "0"
                  }
//snip

This workaround will only work when using Zigbee lights + zigbee2mqtt. In my case, the Philips Hue and Ikea bulbs luckily support the execute_if_off feature for setting the color temperature.

Related issues:

I've been looking for something like this! Does this code work for ambiance lights and RGB bulbs (i'm not using the RGB option in AL)?

I have several ambiance bulbs, old and new.

And just wondering, how/where should i use/apply this snippet?

Thanks!

Kuchiru avatar Jul 22 '24 07:07 Kuchiru

Hi, I would assume that this will also work for RGB lights. Just check what you see z2m write to your bulbs in the z2m frontend logging at debug level.

As for the snippet, to enable this, you would need to do several things:

  1. Install decluttering-card.
  2. Install adaptive lighting.
  3. Group your lights, even if it's one light per group.
  4. Configure adaptive lighting per light group, which means to have one adaptive lighting entity per light group that have defined.
  5. Use the trimmed down snippets of the dashboard and script below - modify them to suit your dashboard/configuration.
  6. Optionally group the Zigbee lights in zigbee2mqtt to allow the lights to react and behave as 'one' light source. Otherwise AL will control them 'one-by-one'.

See below for a (trimmed down) snippet of my dashboard:

decluttering_templates:
  auto_lighting_header_dimmable:
    card:
      type: custom:mushroom-light-card
      entity: light.[[area_id]]
      tap_action:
        action: call-service
        service: script.light_action_in_area
        data:
          action: toggle
          area: '[[area_id]]'
          turn_on_quirk: 'on'

Here I have made groups of all 'areas' that have lights in them, so area_id here can be 'living_room'.

- platform:   group
  name:       Living room
  entities:
    - light.bulb_ikea_e26_1100lm_no_9
    - light.bulb_ikea_e26_1100lm_no_10

See below for a trimmed down version of the script:

light_action_in_area:
  alias:        "Light action in area"
  description:  "Turn on lighting in an area"
  variables:
    entity_light:                 light.{{area}}
    entity_adaptive_lighting:     switch.adaptive_lighting_{{area}}
    entity_adaptive_brightness:   switch.adaptive_lighting_adapt_brightness_{{area}}
    entity_adaptive_color:        switch.adaptive_lighting_adapt_color_{{area}}
    turn_on_quirk:                '{{ turn_on_quirk|tolower if turn_on_quirk is defined else "off" }}'
    turn_on_quirk_color_temp_mired_current: '{{ state_attr(entity_adaptive_lighting, "color_temp_mired") }}'
    bool_light_on:                '{{ is_state(entity_light, "on") }}'
    bool_adaptive_color_enabled:  '{{ is_state(entity_adaptive_color, "on") }}'
  sequence:
  - choose:
    - conditions:
      - condition: or
        conditions:
        - condition: template
          value_template: |-
            {{ action == "on" or (action == "toggle" and is_state(entity_light, "off")) }}
      sequence:
      - service: adaptive_lighting.set_manual_control
        data:
          entity_id: '{{entity_adaptive_lighting}}'
          manual_control: false
      - service: switch.turn_on
        target:
          entity_id: '{{entity_adaptive_brightness}}'
      - if:
        - condition: and
          conditions:
          - condition: template
            value_template: '{{not bool_light_on}}'
          - condition: template
            value_template: '{{turn_on_quirk|lower == "on"}}'
          - condition: template
            value_template: '{{bool_adaptive_color_enabled}}'
        then:
        - repeat:
            for_each: '{{state_attr(entity_light, "entity_id")}}'
            sequence:
            - service: mqtt.publish
              data_template:
                topic: 'zigbee2mqtt/{{state_attr(repeat.item, "friendly_name")}}/set/color_options'
                payload: |
                   {
                     "execute_if_off": "true"
                   }
            - service: mqtt.publish
              data_template:
                topic: 'zigbee2mqtt/{{state_attr(repeat.item, "friendly_name")}}/set'
                ## here the "color_temp" option should be replaced with something related to setting
                ## RGB values for the light
                payload: |
                  {
                    "color_temp": "{{turn_on_quirk_color_temp_mired_current}}",
                    "transition": "0"
                  }
      - service: adaptive_lighting.apply
        data:
          entity_id:        '{{entity_adaptive_lighting}}'
          #[AL v1.21] transition:       '{{states[entity_adaptive_lighting].attributes.configuration.initial_transition}}'
          transition:       2
          adapt_color:      true
          adapt_brightness: true
          turn_on_lights:   true

    - conditions:
        - condition: or
          conditions:
            - condition: template
              value_template: |-
                {{ action == "off" or (action == "toggle" and is_state(entity_light, "on")) }}
      sequence:
      - service: light.turn_off
        data: {}
        target:
          entity_id: "{{entity_light}}"

The script still has some leftovers that I do not care to remove (superfluous 'or' condition, 'and' conditions that can be put into one template condition, etc.)

Also, the adaptive_light.apply should be replaceable with a regular light.turn_on if intercept and multi_light_intercept is enabled in AL. But using adaptive_light.apply works fine for me. (If it does not appear to be broken, do not attempt to fix it.)

Feel free to try this out, but it might have some syntax issues due to the trimming.

YMMV as my configuration has morphed into an Ansible templated beast that I sometimes am afraid of touching.

Groetjes,

djurny avatar Jul 22 '24 18:07 djurny

Hey there @emontnemery, @jbouwh, @bdraco, mind taking a look at this issue as it has been labeled with an integration (mqtt) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of mqtt can trigger bot actions by commenting:

  • @home-assistant close Closes the issue.
  • @home-assistant rename Awesome new title Renames the issue.
  • @home-assistant reopen Reopen the issue.
  • @home-assistant unassign mqtt Removes the current integration label and assignees on the issue, add the integration domain after the command.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component) to the issue.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component) on the issue.

(message by CodeOwnersMention)


mqtt documentation mqtt source (message by IssueLinks)

home-assistant[bot] avatar Jul 27 '24 10:07 home-assistant[bot]

This is not a place for Zigbee2Mqtt support. To see if there is an issue with mqtt I need the mqtt config for the light and the state update. Home Assistant will assign the color temp that Z2M reports back. In Home Assistant color temp can only be set when the light is turned on. The actual state of the color temp the is to be reported by the light.

jbouwh avatar Jul 27 '24 18:07 jbouwh

This is not a place for Zigbee2Mqtt support. To see if there is an issue with mqtt I need the mqtt config for the light and the state update. Home Assistant will assign the color temp that Z2M reports back. In Home Assistant color temp can only be set when the light is turned on. The actual state of the color temp the is to be reported by the light.

Hi Jan, Thanks for your response.

Seems you are already stating the issue:

In Home Assistant color temp can only be set when the light is turned on.

My goal is to set the color temperature of a light that is currently off. My (Ikea and Hue) zigbee bulbs support setting the color_temp when the light is off. This will prevent a color_temp transition of the bulb when it does turn on. (Only brightness will transition from '0' to the brightness set in the light.turn_on service call.)

In order to do this with as little extra effort as possible, I was expecting that a light.turn_on with color_temp set and brightness = 0 will still result in a call to the MQTT component which will reach z2m to set the color_temp without turning on the light.

However, when I do a light.turn_on with brightness = 0, zigbee2mqtt appears to receive nothing. When I issue a light.turn_on with brightness > 0, zigbee2mqtt does receive a command to send something to the bulb.

If this is indeed intended behavior as you implied, then my question is answered.

Groetjes,

djurny avatar Jul 27 '24 20:07 djurny

When the light is turned on without options, the light should report back the correct color temp. It does not seem to make sense to set it when te light is off. HA does not support it.

jbouwh avatar Jul 27 '24 20:07 jbouwh

So it is intended to always transition from the last state that the lamp was on? for example i have my sleep mode set to 1% brightness for all lamps, when i turn a lamp on who’s last state was 100% brightness the light will turn on full blast transitioning to 1%. HA might not support but this kind of QoL would be great.

Kuchiru avatar Jul 27 '24 21:07 Kuchiru

If ha turns a lamp without any additional parameters, then it will I'll just send a state change. If you pick a brightness or color temp from the ui, then ha will send those along. It is up to z2m to send an update to mqtt to reflect to the correct state.

jbouwh avatar Jul 27 '24 23:07 jbouwh

Hi Jan, Not sure why you mention a state report or current state of the light in your replies, as that is not really what I'm interested in knowing in my automations/script.

Perhaps the usecase was not clearly laid out, so let me try to expand a bit on that:

We are using the Adaptive Lighting custom integration that changes color temperature and brightness of lights during the day depending on your location and sunrise/set times. When lights are turned off, the integration still calculates the color temperature/brightness according to it's configuration settings. The lights that are off however are not fed with the new settings. So if a light is turned off during noon, where color temperature is 'cold' and brightness is 'high', these settings are not updated when the light is off.

When these lights are turned on again during evening or nighttime - where Adaptive Lighting would have set low brightness and warm color temperatures, the light will still be set to the state of noon and transition from the 'cold' color temperature to the 'warm' color temperature. Some lights will even transition from the high brightness from noon time (last time the light was on) to the newly calculated brightness. Giving the color temperature explicitly to light.turn_on together with a brightness is also not always supported by all lights (Ikea is a good/bad example of that).

I'm lucky that the Ikea and Hue lights I got, only show this transition for the color temperatures, but it seems others (like @Kuchiru) see this effect also with the brightness of the lights when they are turned on at a different of day.

If I recall I also tried other ways, like light.turn_on with just color_temp and lowest brightness with transition = 0 and then have Adaptive Lighting 'take the wheel', but the result looks clonky and not fluid at all. The results also are not the same across bulb brands and/or types.

So this is where the setting the color temperature for lights that are off comes from. For LiFX lights, the integration offers the lifx.set_state service to do this.

Hope this makes it a bit more clear, as I am not that interested in knowing the current color temperature of the light before turning it on, I just want to prevent any transition the light might start when turning it on, by explicitly setting the color temperature to the one Adaptive Lighting has calculated before turning it on.

Hope that makes my (our) situation more clear?

All in all, I do think it would make sense to have a light.turn_on that supports not sending brightness to the light, but just color temperature, let the light(bulb) decide for itself if it needs or wants to turn on in case it receives such event.

Anyway, I also opened an issue at Adaptive Lighting, perhaps something can be done there as well, or I'll find some sort of "suggestion box" to put this one into.

Thanks for your time!

Groetjes,

djurny avatar Jul 28 '24 01:07 djurny

I mention the state reports as this determines what HA shows as state for the light, not the values sent to the light. So, related to the title of this issue, and the setting happens outside of HA, it is the state report that determines the actual state of the light in most cases. The light on service actually supports sending an on state without the extra attributes AFAIN, or just a single color temp attribute. You can test this from the Service section with the developer tools.

jbouwh avatar Jul 28 '24 07:07 jbouwh

In Home Assistant, users working with Tuya devices are currently limited to using the light.on service to adjust settings like brightness, color, or temperature, which unfortunately turns the lights on even when they are off. However, using the Tuya Cloud API, it’s possible to adjust these settings without toggling the light’s on/off state, allowing for greater control. While this works, it creates an external dependency on the Tuya Cloud, which many users, including myself, find undesirable.

For Zigbee devices, this level of control can be achieved through mqtt.publish, which allows users to adjust settings like brightness or color without affecting the power state of the light. Home Assistant would greatly benefit from a native light.publish or light.set feature that enables users to modify light settings—such as brightness, color, or temperature—without turning them on if they are off, or only adjusting settings for lights that are already on. This would provide more granular control and prevent unwanted lighting activations.

This lack of fine-tuned control is also a primary reason to avoid Matter devices, as the only options provided at that point would be light.on, light.off, and light.toggle, which similarly limits control. Relying on the Tuya Cloud for functionality that should be built into Home Assistant adds an unnecessary dependency, which is why I am in the process of migrating nearly 80 Tuya lights over to Zigbee. This way, I can avoid the need for external dependencies and achieve the control I need directly through Home Assistant.

wjnelson78 avatar Oct 09 '24 17:10 wjnelson78

@jbouwh, I want to add my name to the list here, and try to clarify the problem.

  • There are lots of light controllers that allows you to set the color_temp regardless of the light being on or off.
    • When on, the light would transition to the new temp
    • When off, the light would turn on with that temp next time
  • When you send a state update to HA via MQTT, such as {"state": "ON", "color_mode": "color_temp", "color_temp": 300}, HA correctly updates its internal state
  • When you send a state update to HA via MQTT, such as {"state": "OFF", "color_mode": "color_temp", "color_temp": 300}, HA completely ignores the update
  • When you send a state update to HA via MQTT, such as {"color_mode": "color_temp", "color_temp": 300}, HA completely ignores the update

The real world lights have as a valid, and completely reasonable behavior, that color_temp and brightness can be set independently, whereas HA seems to operate on the idea that color_temp can only ever change in context of the light being on.

What is being asked for here, is that HA's state management system allows the color_temp change to go through, regardless of the overall state of the light - it is simply not relevant what that state is.

oyvindkinsey avatar Dec 20 '24 06:12 oyvindkinsey

@jbouwh, what would be the rationale for not accepting these state changes when the light is off? Is this intentional, a bug, or simply the result of undefined behavior?

oyvindkinsey avatar Dec 20 '24 07:12 oyvindkinsey

@jbouwh, what would be the rationale for not accepting these state changes when the light is off? Is this intentional, a bug, or simply the result of undefined behavior?

It is not supported. An architectural discussion would be needed. A light is supporting color_temp state updates. You can only change the color_temp as a parameter when turning a light on.

jbouwh avatar Dec 20 '24 10:12 jbouwh

@emontnemery, @bdraco - mind chiming in here? I don't think we're asking for a change between two reasonable ways of doing this, but instead are flagging a seemingly illogical and limiting behavior that without a rational purpose can only new understood as a bug. Why would this need to be discussed as an architectural discussion vs be reviewed here?

oyvindkinsey avatar Dec 20 '24 14:12 oyvindkinsey

I am experiencing the same issue as @oyvindkinsey. I've spent the last few days trying to come up with a workaround to prevent a bulb's previous color from being initially flashed when it's turned on with a different color. I've been testing this with IKEA TRÅDFRI smart lights.

In short, my findings confirmed what others have mentioned; it is necessary to have a feature/function that allows us to change a bulb's color without turning it on. The default payload that is being sent by MQTT is usually something like:

{"state":"ON", "color":{"x":0.1,"y":0.2}}

This payload results in the previous color being flashed. What I have tried, is simply publishing a payload with MQTT like so:

{"color":{"x":0.1,"y":0.2}}

And then turning on the bulb with {"state":"ON"} results in a very smooth transition without the previous color being flashed.

Practically, the only thing that is needed is an option in Home Assistant or the MQTT configuration that allows us to change the way the payload is sent by light.turn_on, by allowing us to send color changes without turning the bulb on (as others have mentioned).

I don't think that necessitates an architectural discussion @jbouwh. Unless there is a specific reason for it?

In conclusion, owners of bulbs that support color changes while the bulbs are off, and are using Zigbee2MQTT, would benefit greatly from a light.publish service so that integrations such as Adaptive Lighting work correctly.

cipheredsyntax avatar Dec 20 '24 22:12 cipheredsyntax

Agreed. Same issue with lifx. I understand that not all bulbs support changing the color temperature when they're off, but that shouldn't restrict the ones that do have that capability

AJolly avatar Dec 20 '24 22:12 AJolly

To see what happens, we need to reproduce all the steps to see the underlying issue. What we need is:

  • a configuration payload to test with (in JSON format). You can find this at device level under MQTT info.
  • A set by step plan what is happening and what payloads are set from HA or from Z2M. So: Turning the light with HA-> Payload xxx is sent. Changing the color_temp in HA-> Payload xx is send. Turning the lamp on with a switch -> state xxx is received from Z2M. Changing the color_temp with a switch -> payload xxx is received.
  • For each state change, supply the entity state found in the developers panel.

Without such information it is hard to tell this is a bug in MQTT, a bug in Z2M or the core light component.

jbouwh avatar Dec 21 '24 10:12 jbouwh

It seems a color_temp value is processed correctly when it is received when a light is off. This test passes:

@pytest.mark.parametrize(
    "hass_config",
    [
        {
            mqtt.DOMAIN: {
                light.DOMAIN: {
                    "schema": "json",
                    "name": "test",
                    "state_topic": "test_light_rgb",
                    "command_topic": "test_light_rgb/set",
                    "brightness": True,
                    "color_temp": True,
                    "effect": True,
                    "rgb": True,
                    "xy": True,
                    "hs": True,
                    "qos": "0",
                }
            }
        }
    ],
)
async def test_controlling_state_via_topic(
    hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator
) -> None:
    """Test the controlling of the state via topic."""
    await mqtt_mock_entry()

    state = hass.states.get("light.test")
    assert state.state == STATE_UNKNOWN
    color_modes = [light.ColorMode.COLOR_TEMP, light.ColorMode.HS]
    assert state.attributes.get(light.ATTR_SUPPORTED_COLOR_MODES) == color_modes
    expected_features = (
        light.SUPPORT_EFFECT | light.SUPPORT_FLASH | light.SUPPORT_TRANSITION
    )
    assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == expected_features
    assert state.attributes.get("rgb_color") is None
    assert state.attributes.get("brightness") is None
    assert state.attributes.get("color_temp_kelvin") is None
    assert state.attributes.get("effect") is None
    assert state.attributes.get("xy_color") is None
    assert state.attributes.get("hs_color") is None
    assert not state.attributes.get(ATTR_ASSUMED_STATE)

    # Turn on the light
    async_fire_mqtt_message(
        hass,
        "test_light_rgb",
        '{"state":"ON",'
        '"color":{"r":255,"g":255,"b":255},'
        '"brightness":255,'
        '"color_temp":155,'
        '"effect":"colorloop"}',
    )

    state = hass.states.get("light.test")
    assert state.state == STATE_ON
    assert state.attributes.get("rgb_color") == (255, 255, 255)
    assert state.attributes.get("brightness") == 255
    assert state.attributes.get("color_temp_kelvin") is None  # rgb color has priority
    assert state.attributes.get("effect") == "colorloop"
    assert state.attributes.get("xy_color") == (0.323, 0.329)
    assert state.attributes.get("hs_color") == (0.0, 0.0)

    # Turn on the light
    async_fire_mqtt_message(
        hass,
        "test_light_rgb",
        '{"state":"ON",'
        '"brightness":255,'
        '"color":null,'
        '"color_temp":155,'
        '"effect":"colorloop"}',
    )

    state = hass.states.get("light.test")
    assert state.state == STATE_ON
    assert state.attributes.get("rgb_color") == (
        255,
        253,
        249,
    )  # temp converted to color
    assert state.attributes.get("brightness") == 255
    assert state.attributes.get("color_temp_kelvin") == 6451
    assert state.attributes.get("effect") == "colorloop"
    assert state.attributes.get("xy_color") == (0.328, 0.333)  # temp converted to color
    assert state.attributes.get("hs_color") == (44.098, 2.43)  # temp converted to color

    # Turn the light off
    async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"OFF"}')

    state = hass.states.get("light.test")
    assert state.state == STATE_OFF

    async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON", "brightness":100}')

    light_state = hass.states.get("light.test")

    assert light_state.attributes["brightness"] == 100

    async_fire_mqtt_message(
        hass, "test_light_rgb", '{"state":"ON", "color":{"r":125,"g":125,"b":125}}'
    )

    light_state = hass.states.get("light.test")
    assert light_state.attributes.get("rgb_color") == (255, 255, 255)

    async_fire_mqtt_message(
        hass, "test_light_rgb", '{"state":"ON", "color":{"x":0.135,"y":0.135}}'
    )

    light_state = hass.states.get("light.test")
    assert light_state.attributes.get("xy_color") == (0.141, 0.141)

    async_fire_mqtt_message(
        hass, "test_light_rgb", '{"state":"ON", "color":{"h":180,"s":50}}'
    )

    light_state = hass.states.get("light.test")
    assert light_state.attributes.get("hs_color") == (180.0, 50.0)

    async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON", "color":null}')

    light_state = hass.states.get("light.test")
    assert "hs_color" in light_state.attributes  # Color temp approximation

    async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON", "color_temp":155}')

    light_state = hass.states.get("light.test")
    assert light_state.attributes.get("color_temp") == 155

    async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON", "color_temp":null}')

    light_state = hass.states.get("light.test")
    assert light_state.attributes.get("color_temp") is None

    async_fire_mqtt_message(
        hass, "test_light_rgb", '{"state":"ON", "effect":"colorloop"}'
    )

    light_state = hass.states.get("light.test")
    assert light_state.attributes.get("effect") == "colorloop"

    async_fire_mqtt_message(
        hass,
        "test_light_rgb",
        '{"state":"ON",'
        '"color":{"r":255,"g":255,"b":255},'
        '"brightness":128,'
        '"color_temp":155,'
        '"effect":"colorloop"}',
    )
    light_state = hass.states.get("light.test")
    assert light_state.state == STATE_ON
    assert light_state.attributes.get("brightness") == 128

    async_fire_mqtt_message(
        hass,
        "test_light_rgb",
        '{"state":"OFF","brightness":0}',
    )
    light_state = hass.states.get("light.test")
    assert light_state.state == STATE_OFF
    assert light_state.attributes.get("brightness") is None

    # Simulate the lights color temp has been changed
    # while it was switched off
    async_fire_mqtt_message(
        hass,
        "test_light_rgb",
        '{"state":"OFF","color_temp":201}',
    )
    light_state = hass.states.get("light.test")
    assert light_state.state == STATE_OFF
    # Color temp attribute is not exposed while the lamp is off
    assert light_state.attributes.get("color_temp") is None

    # test previous zero brightness received was ignored and brightness is restored
    # see if the latest color_temp value received is restored
    async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON"}')
    light_state = hass.states.get("light.test")
    assert light_state.attributes.get("brightness") == 128
    assert light_state.attributes.get("color_temp") == 201

    # A `0` brightness value is ignored when a light is turned on
    async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON","brightness":0}')
    light_state = hass.states.get("light.test")
    assert light_state.attributes.get("brightness") == 128

jbouwh avatar Dec 21 '24 11:12 jbouwh

https://github.com/home-assistant/core/pull/133715

jbouwh avatar Dec 21 '24 11:12 jbouwh

@jbouwh , thank you, I really appreciate you looking at this!

I reviewed your additional test, and while it suggests that incoming color changes are retained, it also raises the question as to how such state is made available to automation/debugging, as well as how the visible change is handled by the system. As an example, if the update can only be observed once the light enters the ON state, what does that means for automations triggering on state change? Would the change event trigger when the update was made, or when it was made visible?

I'll try to put together a more comprehensive test/bug report, but most likely your test doesn't cover the specific scenario represented by the many heavily used integrations currently having to work around this. Occam's Razor - the specific APIs involved here are simple, and the level/quality of effort put into resolving these issues are substantial, so it seems likely that there is a gap, even if we've been able to clearly articulate it due to unfamiliarity with the nomenclature and principles.

oyvindkinsey avatar Dec 21 '24 15:12 oyvindkinsey

Would the change event trigger when the update was made, or when it was made visible?

Could there for instance be a race condition, where the color change is emitted after the state change? Presumably these are not emitted atomically as a single composite event?

oyvindkinsey avatar Dec 21 '24 16:12 oyvindkinsey

Note that the state updates received determine the state entity. When a light is turned on it can be turned on with a new color_temp, but that does NOT change the state, unless the light is in pessimistic mode.

jbouwh avatar Dec 21 '24 18:12 jbouwh

I believe I have the same issue. I'm converting from a Philips Hue bridge to HA+Z2M. I previously had automations that would change the color of the lights while off, so that the next time I turned them on (via light switch) they would already have the correct color. That does not appear to work with my new setup.

ams2990 avatar Jan 02 '25 04:01 ams2990

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest Home Assistant version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.