Make ozw CCT use device attributes instead of hard coded values (#38054)

This commit is contained in:
Patrick 2020-08-04 13:15:21 -05:00 committed by GitHub
parent 86fc977ff5
commit 0780650015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 21 deletions

View File

@ -114,7 +114,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
# Filter out CommandClasses we're definitely not interested in.
if value.command_class in [
CommandClass.CONFIGURATION,
CommandClass.VERSION,
CommandClass.MANUFACTURER_SPECIFIC,
]:

View File

@ -250,6 +250,16 @@ DISCOVERY_SCHEMAS = (
const.DISC_INDEX: ValueIndex.SWITCH_COLOR_CHANNELS,
const.DISC_OPTIONAL: True,
},
"min_kelvin": {
const.DISC_COMMAND_CLASS: (CommandClass.CONFIGURATION,),
const.DISC_INDEX: 81, # PR for upstream to add SWITCH_COLOR_CT_WARM
const.DISC_OPTIONAL: True,
},
"max_kelvin": {
const.DISC_COMMAND_CLASS: (CommandClass.CONFIGURATION,),
const.DISC_INDEX: 82, # PR for upstream to add SWITCH_COLOR_CT_COLD
const.DISC_OPTIONAL: True,
},
},
},
{ # All other text/numeric sensors

View File

@ -30,9 +30,6 @@ COLOR_CHANNEL_COLD_WHITE = 0x02
COLOR_CHANNEL_RED = 0x04
COLOR_CHANNEL_GREEN = 0x08
COLOR_CHANNEL_BLUE = 0x10
TEMP_COLOR_MAX = 500 # mired equivalent to 2000K
TEMP_COLOR_MIN = 154 # mired equivalent to 6500K
TEMP_COLOR_DIFF = TEMP_COLOR_MAX - TEMP_COLOR_MIN
async def async_setup_entry(hass, config_entry, async_add_entities):
@ -71,6 +68,9 @@ class ZwaveLight(ZWaveDeviceEntity, LightEntity):
self._white = None
self._ct = None
self._supported_features = SUPPORT_BRIGHTNESS
self._min_mireds = 153 # 6500K as a safe default
self._max_mireds = 370 # 2700K as a safe default
# make sure that supported features is correctly set
self.on_value_update()
@ -136,6 +136,16 @@ class ZwaveLight(ZWaveDeviceEntity, LightEntity):
"""Return the color temperature."""
return self._ct
@property
def min_mireds(self):
"""Return the coldest color_temp that this light supports."""
return self._min_mireds
@property
def max_mireds(self):
"""Return the warmest color_temp that this light supports."""
return self._max_mireds
@callback
def async_set_duration(self, **kwargs):
"""Set the transition time for the brightness value.
@ -209,7 +219,11 @@ class ZwaveLight(ZWaveDeviceEntity, LightEntity):
0,
min(
255,
round((TEMP_COLOR_MAX - round(color_temp)) / TEMP_COLOR_DIFF * 255),
round(
(self._max_mireds - color_temp)
/ (self._max_mireds - self._min_mireds)
* 255
),
),
)
warm = 255 - cold
@ -241,16 +255,26 @@ class ZwaveLight(ZWaveDeviceEntity, LightEntity):
# Color Data String
data = self.values.color.data[ATTR_VALUE]
# RGB is always present in the openzwave color data string.
# RGB is always present in the OpenZWave color data string.
rgb = [int(data[1:3], 16), int(data[3:5], 16), int(data[5:7], 16)]
self._hs = color_util.color_RGB_to_hs(*rgb)
# Parse remaining color channels. Openzwave appends white channels
# Parse remaining color channels. OpenZWave appends white channels
# that are present.
index = 7
temp_warm = 0
temp_cold = 0
# Update color temp limits.
if self.values.min_kelvin:
self._max_mireds = color_util.color_temperature_kelvin_to_mired(
self.values.min_kelvin.data[ATTR_VALUE]
)
if self.values.max_kelvin:
self._min_mireds = color_util.color_temperature_kelvin_to_mired(
self.values.max_kelvin.data[ATTR_VALUE]
)
# Warm white
if self._color_channels & COLOR_CHANNEL_WARM_WHITE:
self._white = int(data[index : index + 2], 16)
@ -264,13 +288,12 @@ class ZwaveLight(ZWaveDeviceEntity, LightEntity):
temp_cold = self._white
# Calculate color temps based on white LED status
if temp_cold > 0:
self._ct = round(TEMP_COLOR_MAX - ((temp_cold / 255) * TEMP_COLOR_DIFF))
# Only used if CW channel missing
elif temp_warm > 0:
self._ct = round(TEMP_COLOR_MAX - temp_warm)
if temp_cold or temp_warm:
self._ct = round(
self._max_mireds
- ((temp_cold / 255) * (self._max_mireds - self._min_mireds))
)
# If no rgb channels supported, report None.
if not (
self._color_channels & COLOR_CHANNEL_RED
or self._color_channels & COLOR_CHANNEL_GREEN

View File

@ -284,7 +284,7 @@ async def test_light(hass, light_data, light_msg, light_rgb_msg, sent_messages):
assert state.attributes["xy_color"] == (0.519, 0.429)
# Test setting color temp
new_color = 465
new_color = 200
await hass.services.async_call(
"light",
"turn_on",
@ -298,14 +298,14 @@ async def test_light(hass, light_data, light_msg, light_rgb_msg, sent_messages):
msg = sent_messages[-2]
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
assert msg["payload"] == {"Value": "#000000e51a", "ValueIDKey": 659341335}
assert msg["payload"] == {"Value": "#00000037c8", "ValueIDKey": 659341335}
# Feedback on state
light_msg.decode()
light_msg.payload["Value"] = byte_to_zwave_brightness(255)
light_msg.encode()
light_rgb_msg.decode()
light_rgb_msg.payload["Value"] = "#000000e51a"
light_rgb_msg.payload["Value"] = "#00000037c8"
light_rgb_msg.encode()
receive_message(light_msg)
receive_message(light_rgb_msg)
@ -314,7 +314,7 @@ async def test_light(hass, light_data, light_msg, light_rgb_msg, sent_messages):
state = hass.states.get("light.led_bulb_6_multi_colour_level")
assert state is not None
assert state.state == "on"
assert state.attributes["color_temp"] == 465
assert state.attributes["color_temp"] == 200
# Test setting invalid color temp
new_color = 120
@ -347,7 +347,7 @@ async def test_light(hass, light_data, light_msg, light_rgb_msg, sent_messages):
state = hass.states.get("light.led_bulb_6_multi_colour_level")
assert state is not None
assert state.state == "on"
assert state.attributes["color_temp"] == 154
assert state.attributes["color_temp"] == 153
async def test_no_rgb_light(hass, light_no_rgb_data, light_no_rgb_msg, sent_messages):
@ -486,6 +486,9 @@ async def test_wc_light(hass, light_wc_data, light_msg, light_rgb_msg, sent_mess
assert state is not None
assert state.state == "off"
assert state.attributes["min_mireds"] == 153
assert state.attributes["max_mireds"] == 370
# Turn on the light
new_color = 190
await hass.services.async_call(
@ -497,14 +500,14 @@ async def test_wc_light(hass, light_wc_data, light_msg, light_rgb_msg, sent_mess
assert len(sent_messages) == 2
msg = sent_messages[-2]
assert msg["topic"] == "OpenZWave/1/command/setvalue/"
assert msg["payload"] == {"Value": "#0000001be4", "ValueIDKey": 659341335}
assert msg["payload"] == {"Value": "#0000002bd4", "ValueIDKey": 659341335}
# Feedback on state
light_msg.decode()
light_msg.payload["Value"] = byte_to_zwave_brightness(255)
light_msg.encode()
light_rgb_msg.decode()
light_rgb_msg.payload["Value"] = "#0000001be4"
light_rgb_msg.payload["Value"] = "#0000002bd4"
light_rgb_msg.encode()
receive_message(light_msg)
receive_message(light_rgb_msg)
@ -513,7 +516,7 @@ async def test_wc_light(hass, light_wc_data, light_msg, light_rgb_msg, sent_mess
state = hass.states.get("light.led_bulb_6_multi_colour_level")
assert state is not None
assert state.state == "on"
assert state.attributes["color_temp"] == 191
assert state.attributes["color_temp"] == 190
async def test_new_ozw_light(hass, light_new_ozw_data, light_msg, sent_messages):