Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for light color modes #47720

Merged
merged 11 commits into from
Mar 16, 2021

Conversation

emontnemery
Copy link
Contributor

@emontnemery emontnemery commented Mar 10, 2021

Proposed change

Add support for light color modes, background in home-assistant/architecture#519.
The color mode will be stored in the light's state, but should not be passed to the turn_on service call.
When turning on the light, the color mode is non ambiguous because only one color may be given.

Colors will no longer be force-converted through hs color space when updating state or in a turn_on call, instead the light's native color space will be respected.

New attributes:

ATTR_COLOR_MODE
ATTR_SUPPORTED_COLOR_MODES
ATTR_RGBW_COLOR
ATTR_RGBWW_COLOR

Defined color modes:

COLOR_MODES = {
    COLOR_MODE_ONOFF,  # The light can be turned on or off. This mode must be the only supported mode if supported by the light
    COLOR_MODE_DIMMER,  # The light can be dimmed. This mode must be the only supported mode if supported by the light
    COLOR_MODE_COLOR_TEMP,  # The light can be dimmed and its color temperature is present in the state.
    COLOR_MODE_HS,  # The light can be dimmed and its color is present in the state as an (h, s) tuple (no brightness).
    COLOR_MODE_XY,  # The light can be dimmed and its color is present in the state as an (x, y) tuple (no brightness).
    COLOR_MODE_RGB,  # The light can be dimmed and its color is present in the state as an (r, g, b) tuple (not normalized).
    COLOR_MODE_RGBW,  # The light can be dimmed and its color is present in the state as an (r, g, b, w) tuple (not normalized).
    COLOR_MODE_RGBWW,  # The light can be dimmed and its color is present in the state as an (r, g, b, cw, ww) tuple (not normalized).
    COLOR_MODE_UNKNOWN,  # The light has reported an ambiguous state (e.g. no brightness for a light which supports `COLOR_MODE_DIMMER`)
}

New methods added to the base component LightEntity:

  • color_mode
  • supported_color_modes
  • rgb_color
  • rgbw_color
  • rgbww_color
  • xy_color

For backwards compatibility:

  • If the light does not implement supported_color_modes, it will be calculeted based on supported_features
  • If the light does not implement color_mode, current color_mode will be guessed in the following order:
    • COLOR_MODE_RGBW if the light's white_value and hs_color are not None
    • COLOR_MODE_HS if the light's hs_color is not None
    • COLOR_MODE_COLOR_TEMP if the light's color_temp is not None
    • COLOR_MODE_DIMMER if the light's brihtness is not None
    • COLOR_MODE_NONE otherwise
  • If the light does not implement supported_color_modes, a turn_on service call with ATTR_RGBW_COLOR will be converted to ATTR_HS_COLOR + ATTR_WHITE_VALUE.

Deprecated:

SUPPORT_BRIGHTNESS = 1
SUPPORT_COLOR_TEMP = 2
SUPPORT_COLOR = 16

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Example entry for configuration.yaml:

# Example configuration.yaml

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue:
  • Link to documentation pull request:

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • The code has been formatted using Black (black --fast homeassistant tests)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • Untested files have been added to .coveragerc.

The integration reached or maintains the following Integration Quality Scale:

  • No score or internal
  • 🥈 Silver
  • 🥇 Gold
  • 🏆 Platinum

To help with the load of incoming pull requests:

@probot-home-assistant
Copy link

Hey there @emlove, mind taking a look at this pull request as its been labeled with an integration (zerproc) you are listed as a codeowner for? Thanks!
(message by CodeOwnersMention)

@probot-home-assistant
Copy link

Hey there @rytilahti, @zewelor, @shenxn, mind taking a look at this pull request as its been labeled with an integration (yeelight) you are listed as a codeowner for? Thanks!
(message by CodeOwnersMention)

@project-bot project-bot bot added this to Needs review in Dev Mar 10, 2021
@balloob
Copy link
Member

balloob commented Mar 10, 2021

I would expect Google, Alexa and Homekit requiring updates because of this PR

# If a color is specified, convert to the color space supported by the light
# Backwards compatibility: Fall back to hs color if light.supported_color_modes
# is not implemented
if ATTR_HS_COLOR or ATTR_RGB_COLOR or ATTR_XY_COLOR in params:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tests if ATTR_HS_COLOR is truthy, ATTR_RGB_COLOR is truthy, or ATTR_XY_COLOR in params. The first two are defined so this code is always executed?

Suggested change
if ATTR_HS_COLOR or ATTR_RGB_COLOR or ATTR_XY_COLOR in params:
if ATTR_HS_COLOR in params or ATTR_RGB_COLOR in params or ATTR_XY_COLOR in params:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, tests are needed for the new code

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't you use intersection here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if more readable:

if params.keys() & {ATTR_HS_COLOR, ATTR_RGB_COLOR, ATTR_XY_COLOR}:

You can also do

if any(key in params for key in (ATTR_HS_COLOR, ATTR_RGB_COLOR, ATTR_XY_COLOR)):

if (xy_color := params.pop(ATTR_XY_COLOR, None)) is not None:
params[ATTR_HS_COLOR] = color_util.color_xy_to_hs(*xy_color)

elif COLOR_MODE_RGB in supported_color_modes:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure every fallback has a test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, the tests for the light component needs to be updated to test the new features as well as all the backwards compatibility cases.

):
# Backwards compatibility for rgbw_color added in 2021.4
# Add warning in 2021.6, remove in 2021.10
r, g, b = color_util.color_hs_to_RGB(*self.hs_color)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
r, g, b = color_util.color_hs_to_RGB(*self.hs_color)
# pylint: disable=invalid-name
r, g, b = color_util.color_hs_to_RGB(*self.hs_color)

@emontnemery
Copy link
Contributor Author

I would expect Google, Alexa and Homekit requiring updates because of this PR

Does it mean those integrations will need to be updated to handle the new colour modes, rgbw and rgbww?

@emontnemery
Copy link
Contributor Author

@Koenkk could you have a look at this from a z2m perspective?

@emontnemery
Copy link
Contributor Author

emontnemery commented Mar 12, 2021

@dmulcahey, @Kane610 Can you review the proposal from the perspective of zha / deconz?

@zha
Copy link

zha commented Mar 12, 2021

@zha, @Kane610 Can you review the proposal from the perspective of zha / deconz?

I am sure you mentioned the wrong person 😊. Very interesting project though.

@Adminiuga
Copy link
Contributor

Nothing jumps out for ZHA. LGTM

Please notify me when this gets merged (in case I miss it), and I'll test it, update ZHA if needed.

@Koenkk
Copy link
Contributor

Koenkk commented Mar 12, 2021

@emontnemery looks good, 2 things however:

{"state": "ON", "brightness": 100, "color": {"x": 0.7, "y": 0.3"}, "color_mode": "color_mode_xy"}
  • Question: what happens if there is no color_mode property in the payload? I would expect COLOR_MODE_UNKNOWN to be used in this case.

The "color_mode": "color_mode_xy" looks a bit strange to me since color_mode is in both the property and value. What about just: "color_mode": "xy"?

Comment on lines +282 to +283
elif ATTR_HS_COLOR in params and COLOR_MODE_HS not in supported_color_modes:
hs_color = params.pop(ATTR_HS_COLOR)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could go all wallrus:

Suggested change
elif ATTR_HS_COLOR in params and COLOR_MODE_HS not in supported_color_modes:
hs_color = params.pop(ATTR_HS_COLOR)
elif COLOR_MODE_HS not in supported_color_modes and (hs_color := params.pop(ATTR_HS_COLOR, None) is not None:

Copy link
Contributor Author

@emontnemery emontnemery Mar 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It becomes 4 lines instead of 2 after formatting though:

        elif (
            COLOR_MODE_HS not in supported_color_modes
            and (hs_color := params.pop(ATTR_HS_COLOR, None)) is not None
        ):

color_mode = self._light_internal_color_mode

if color_mode not in self._light_internal_supported_color_modes:
_LOGGER.debug(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we log this as error the first time per-entity?

Copy link
Contributor Author

@emontnemery emontnemery Mar 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should start doing that in 1-2 releases, not yet. I added a comment in 63e4f4d.

Dev automation moved this from Needs review to Reviewer approved Mar 12, 2021
@emontnemery
Copy link
Contributor Author

emontnemery commented Mar 15, 2021

@Koenkk

  • COLOR_MODE_BRIGHTNESS looks like a more logical name for COLOR_MODE_DIMMER

I agree, changed in 577f787.

  • Question: what happens if there is no color_mode property in the payload? I would expect COLOR_MODE_UNKNOWN to be used in this case.

For an MQTT JSON light, I think we should add two new configuration variables:

  • color_mode: set to True if the light will report its color mode, False otherwise.
  • supported_color_modes: A list of supported color modes

For a light which is configured with color_mode=True, it would be an error if we receive a state update dict without the color_mode, or a color_mode not included in supported_color_modes.

The "color_mode": "color_mode_xy" looks a bit strange to me since color_mode is in both the property and value. What about just: "color_mode": "xy"?

I agree, changed in 577f787.

Dev automation moved this from Reviewer approved to Cancelled Mar 16, 2021
@emontnemery emontnemery reopened this Mar 16, 2021
Dev automation moved this from Cancelled to Incoming Mar 16, 2021
@emontnemery emontnemery merged commit 5f2326f into home-assistant:dev Mar 16, 2021
Dev automation moved this from Incoming to Done Mar 16, 2021
@Koenkk
Copy link
Contributor

Koenkk commented Mar 16, 2021

@emontnemery big thanks, when looking at the changes files I don't see anything changed in MQTT. Does this mean a new merge request has to be done for this? (or can I already test this out somehow)

Forget about this, just saw #47993

@github-actions github-actions bot locked and limited conversation to collaborators Mar 17, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Dev
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

9 participants