Use supported_color_modes in google_assistant (#49176)

* Use supported_color_modes in google_assistant

* Fix tests
This commit is contained in:
Erik Montnemery 2021-04-14 09:18:22 +02:00 committed by GitHub
parent 44beff31c2
commit 1a5068f71d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 90 deletions

View File

@ -408,7 +408,8 @@ class GoogleEntity:
state = self.state state = self.state
domain = state.domain domain = state.domain
features = state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) attributes = state.attributes
features = attributes.get(ATTR_SUPPORTED_FEATURES, 0)
if not isinstance(features, int): if not isinstance(features, int):
_LOGGER.warning( _LOGGER.warning(
@ -423,7 +424,7 @@ class GoogleEntity:
self._traits = [ self._traits = [
Trait(self.hass, state, self.config) Trait(self.hass, state, self.config)
for Trait in trait.TRAITS for Trait in trait.TRAITS
if Trait.supported(domain, features, device_class) if Trait.supported(domain, features, device_class, attributes)
] ]
return self._traits return self._traits

View File

@ -212,10 +212,11 @@ class BrightnessTrait(_Trait):
commands = [COMMAND_BRIGHTNESS_ABSOLUTE] commands = [COMMAND_BRIGHTNESS_ABSOLUTE]
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, attributes):
"""Test if state is supported.""" """Test if state is supported."""
color_modes = attributes.get(light.ATTR_SUPPORTED_COLOR_MODES, [])
if domain == light.DOMAIN: if domain == light.DOMAIN:
return features & light.SUPPORT_BRIGHTNESS return any(mode in color_modes for mode in light.COLOR_MODES_BRIGHTNESS)
return False return False
@ -267,7 +268,7 @@ class CameraStreamTrait(_Trait):
stream_info = None stream_info = None
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
if domain == camera.DOMAIN: if domain == camera.DOMAIN:
return features & camera.SUPPORT_STREAM return features & camera.SUPPORT_STREAM
@ -308,7 +309,7 @@ class OnOffTrait(_Trait):
commands = [COMMAND_ONOFF] commands = [COMMAND_ONOFF]
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
return domain in ( return domain in (
group.DOMAIN, group.DOMAIN,
@ -362,23 +363,26 @@ class ColorSettingTrait(_Trait):
commands = [COMMAND_COLOR_ABSOLUTE] commands = [COMMAND_COLOR_ABSOLUTE]
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, attributes):
"""Test if state is supported.""" """Test if state is supported."""
if domain != light.DOMAIN: if domain != light.DOMAIN:
return False return False
return features & light.SUPPORT_COLOR_TEMP or features & light.SUPPORT_COLOR color_modes = attributes.get(light.ATTR_SUPPORTED_COLOR_MODES, [])
return light.COLOR_MODE_COLOR_TEMP in color_modes or any(
mode in color_modes for mode in light.COLOR_MODES_COLOR
)
def sync_attributes(self): def sync_attributes(self):
"""Return color temperature attributes for a sync request.""" """Return color temperature attributes for a sync request."""
attrs = self.state.attributes attrs = self.state.attributes
features = attrs.get(ATTR_SUPPORTED_FEATURES, 0) color_modes = attrs.get(light.ATTR_SUPPORTED_COLOR_MODES, [])
response = {} response = {}
if features & light.SUPPORT_COLOR: if any(mode in color_modes for mode in light.COLOR_MODES_COLOR):
response["colorModel"] = "hsv" response["colorModel"] = "hsv"
if features & light.SUPPORT_COLOR_TEMP: if light.COLOR_MODE_COLOR_TEMP in color_modes:
# Max Kelvin is Min Mireds K = 1000000 / mireds # Max Kelvin is Min Mireds K = 1000000 / mireds
# Min Kelvin is Max Mireds K = 1000000 / mireds # Min Kelvin is Max Mireds K = 1000000 / mireds
response["colorTemperatureRange"] = { response["colorTemperatureRange"] = {
@ -394,10 +398,10 @@ class ColorSettingTrait(_Trait):
def query_attributes(self): def query_attributes(self):
"""Return color temperature query attributes.""" """Return color temperature query attributes."""
features = self.state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) color_modes = self.state.attributes.get(light.ATTR_SUPPORTED_COLOR_MODES, [])
color = {} color = {}
if features & light.SUPPORT_COLOR: if any(mode in color_modes for mode in light.COLOR_MODES_COLOR):
color_hs = self.state.attributes.get(light.ATTR_HS_COLOR) color_hs = self.state.attributes.get(light.ATTR_HS_COLOR)
brightness = self.state.attributes.get(light.ATTR_BRIGHTNESS, 1) brightness = self.state.attributes.get(light.ATTR_BRIGHTNESS, 1)
if color_hs is not None: if color_hs is not None:
@ -407,7 +411,7 @@ class ColorSettingTrait(_Trait):
"value": brightness / 255, "value": brightness / 255,
} }
if features & light.SUPPORT_COLOR_TEMP: if light.COLOR_MODE_COLOR_TEMP in color_modes:
temp = self.state.attributes.get(light.ATTR_COLOR_TEMP) temp = self.state.attributes.get(light.ATTR_COLOR_TEMP)
# Some faulty integrations might put 0 in here, raising exception. # Some faulty integrations might put 0 in here, raising exception.
if temp == 0: if temp == 0:
@ -495,7 +499,7 @@ class SceneTrait(_Trait):
commands = [COMMAND_ACTIVATE_SCENE] commands = [COMMAND_ACTIVATE_SCENE]
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
return domain in (scene.DOMAIN, script.DOMAIN) return domain in (scene.DOMAIN, script.DOMAIN)
@ -531,7 +535,7 @@ class DockTrait(_Trait):
commands = [COMMAND_DOCK] commands = [COMMAND_DOCK]
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
return domain == vacuum.DOMAIN return domain == vacuum.DOMAIN
@ -565,7 +569,7 @@ class StartStopTrait(_Trait):
commands = [COMMAND_STARTSTOP, COMMAND_PAUSEUNPAUSE] commands = [COMMAND_STARTSTOP, COMMAND_PAUSEUNPAUSE]
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
if domain == vacuum.DOMAIN: if domain == vacuum.DOMAIN:
return True return True
@ -709,7 +713,7 @@ class TemperatureSettingTrait(_Trait):
google_to_preset = {value: key for key, value in preset_to_google.items()} google_to_preset = {value: key for key, value in preset_to_google.items()}
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
if domain == climate.DOMAIN: if domain == climate.DOMAIN:
return True return True
@ -976,7 +980,7 @@ class HumiditySettingTrait(_Trait):
commands = [COMMAND_SET_HUMIDITY] commands = [COMMAND_SET_HUMIDITY]
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
if domain == humidifier.DOMAIN: if domain == humidifier.DOMAIN:
return True return True
@ -1059,7 +1063,7 @@ class LockUnlockTrait(_Trait):
commands = [COMMAND_LOCKUNLOCK] commands = [COMMAND_LOCKUNLOCK]
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
return domain == lock.DOMAIN return domain == lock.DOMAIN
@ -1120,7 +1124,7 @@ class ArmDisArmTrait(_Trait):
} }
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
return domain == alarm_control_panel.DOMAIN return domain == alarm_control_panel.DOMAIN
@ -1236,7 +1240,7 @@ class FanSpeedTrait(_Trait):
} }
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
if domain == fan.DOMAIN: if domain == fan.DOMAIN:
return features & fan.SUPPORT_SET_SPEED return features & fan.SUPPORT_SET_SPEED
@ -1349,7 +1353,7 @@ class ModesTrait(_Trait):
} }
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
if domain == input_select.DOMAIN: if domain == input_select.DOMAIN:
return True return True
@ -1518,7 +1522,7 @@ class InputSelectorTrait(_Trait):
SYNONYMS = {} SYNONYMS = {}
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
if domain == media_player.DOMAIN and ( if domain == media_player.DOMAIN and (
features & media_player.SUPPORT_SELECT_SOURCE features & media_player.SUPPORT_SELECT_SOURCE
@ -1591,7 +1595,7 @@ class OpenCloseTrait(_Trait):
commands = [COMMAND_OPENCLOSE, COMMAND_OPENCLOSE_RELATIVE] commands = [COMMAND_OPENCLOSE, COMMAND_OPENCLOSE_RELATIVE]
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
if domain == cover.DOMAIN: if domain == cover.DOMAIN:
return True return True
@ -1727,7 +1731,7 @@ class VolumeTrait(_Trait):
commands = [COMMAND_SET_VOLUME, COMMAND_VOLUME_RELATIVE, COMMAND_MUTE] commands = [COMMAND_SET_VOLUME, COMMAND_VOLUME_RELATIVE, COMMAND_MUTE]
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if trait is supported.""" """Test if trait is supported."""
if domain == media_player.DOMAIN: if domain == media_player.DOMAIN:
return features & ( return features & (
@ -1915,7 +1919,7 @@ class TransportControlTrait(_Trait):
] ]
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
if domain == media_player.DOMAIN: if domain == media_player.DOMAIN:
for feature in MEDIA_COMMAND_SUPPORT_MAPPING.values(): for feature in MEDIA_COMMAND_SUPPORT_MAPPING.values():
@ -2034,7 +2038,7 @@ class MediaStateTrait(_Trait):
} }
@staticmethod @staticmethod
def supported(domain, features, device_class): def supported(domain, features, device_class, _):
"""Test if state is supported.""" """Test if state is supported."""
return domain == media_player.DOMAIN return domain == media_player.DOMAIN

View File

@ -1171,7 +1171,7 @@ async def test_sync_message_recovery(hass, caplog):
"on", "on",
{ {
"min_mireds": "badvalue", "min_mireds": "badvalue",
"supported_features": hass.components.light.SUPPORT_COLOR_TEMP, "supported_color_modes": ["color_temp"],
}, },
) )
@ -1220,7 +1220,7 @@ async def test_query_recover(hass, caplog):
"light.good", "light.good",
"on", "on",
{ {
"supported_features": hass.components.light.SUPPORT_BRIGHTNESS, "supported_color_modes": ["brightness"],
"brightness": 50, "brightness": 50,
}, },
) )
@ -1228,7 +1228,7 @@ async def test_query_recover(hass, caplog):
"light.bad", "light.bad",
"on", "on",
{ {
"supported_features": hass.components.light.SUPPORT_BRIGHTNESS, "supported_color_modes": ["brightness"],
"brightness": "shoe", "brightness": "shoe",
}, },
) )

View File

@ -70,10 +70,15 @@ PIN_DATA = helpers.RequestData(
) )
async def test_brightness_light(hass): @pytest.mark.parametrize(
"supported_color_modes", [["brightness"], ["hs"], ["color_temp"]]
)
async def test_brightness_light(hass, supported_color_modes):
"""Test brightness trait support for light domain.""" """Test brightness trait support for light domain."""
assert helpers.get_google_type(light.DOMAIN, None) is not None assert helpers.get_google_type(light.DOMAIN, None) is not None
assert trait.BrightnessTrait.supported(light.DOMAIN, light.SUPPORT_BRIGHTNESS, None) assert trait.BrightnessTrait.supported(
light.DOMAIN, 0, None, {"supported_color_modes": supported_color_modes}
)
trt = trait.BrightnessTrait( trt = trait.BrightnessTrait(
hass, hass,
@ -111,7 +116,9 @@ async def test_camera_stream(hass):
{"external_url": "https://example.com"}, {"external_url": "https://example.com"},
) )
assert helpers.get_google_type(camera.DOMAIN, None) is not None assert helpers.get_google_type(camera.DOMAIN, None) is not None
assert trait.CameraStreamTrait.supported(camera.DOMAIN, camera.SUPPORT_STREAM, None) assert trait.CameraStreamTrait.supported(
camera.DOMAIN, camera.SUPPORT_STREAM, None, None
)
trt = trait.CameraStreamTrait( trt = trait.CameraStreamTrait(
hass, State("camera.bla", camera.STATE_IDLE, {}), BASIC_CONFIG hass, State("camera.bla", camera.STATE_IDLE, {}), BASIC_CONFIG
@ -140,7 +147,7 @@ async def test_camera_stream(hass):
async def test_onoff_group(hass): async def test_onoff_group(hass):
"""Test OnOff trait support for group domain.""" """Test OnOff trait support for group domain."""
assert helpers.get_google_type(group.DOMAIN, None) is not None assert helpers.get_google_type(group.DOMAIN, None) is not None
assert trait.OnOffTrait.supported(group.DOMAIN, 0, None) assert trait.OnOffTrait.supported(group.DOMAIN, 0, None, None)
trt_on = trait.OnOffTrait(hass, State("group.bla", STATE_ON), BASIC_CONFIG) trt_on = trait.OnOffTrait(hass, State("group.bla", STATE_ON), BASIC_CONFIG)
@ -166,7 +173,7 @@ async def test_onoff_group(hass):
async def test_onoff_input_boolean(hass): async def test_onoff_input_boolean(hass):
"""Test OnOff trait support for input_boolean domain.""" """Test OnOff trait support for input_boolean domain."""
assert helpers.get_google_type(input_boolean.DOMAIN, None) is not None assert helpers.get_google_type(input_boolean.DOMAIN, None) is not None
assert trait.OnOffTrait.supported(input_boolean.DOMAIN, 0, None) assert trait.OnOffTrait.supported(input_boolean.DOMAIN, 0, None, None)
trt_on = trait.OnOffTrait(hass, State("input_boolean.bla", STATE_ON), BASIC_CONFIG) trt_on = trait.OnOffTrait(hass, State("input_boolean.bla", STATE_ON), BASIC_CONFIG)
@ -194,7 +201,7 @@ async def test_onoff_input_boolean(hass):
async def test_onoff_switch(hass): async def test_onoff_switch(hass):
"""Test OnOff trait support for switch domain.""" """Test OnOff trait support for switch domain."""
assert helpers.get_google_type(switch.DOMAIN, None) is not None assert helpers.get_google_type(switch.DOMAIN, None) is not None
assert trait.OnOffTrait.supported(switch.DOMAIN, 0, None) assert trait.OnOffTrait.supported(switch.DOMAIN, 0, None, None)
trt_on = trait.OnOffTrait(hass, State("switch.bla", STATE_ON), BASIC_CONFIG) trt_on = trait.OnOffTrait(hass, State("switch.bla", STATE_ON), BASIC_CONFIG)
@ -225,7 +232,7 @@ async def test_onoff_switch(hass):
async def test_onoff_fan(hass): async def test_onoff_fan(hass):
"""Test OnOff trait support for fan domain.""" """Test OnOff trait support for fan domain."""
assert helpers.get_google_type(fan.DOMAIN, None) is not None assert helpers.get_google_type(fan.DOMAIN, None) is not None
assert trait.OnOffTrait.supported(fan.DOMAIN, 0, None) assert trait.OnOffTrait.supported(fan.DOMAIN, 0, None, None)
trt_on = trait.OnOffTrait(hass, State("fan.bla", STATE_ON), BASIC_CONFIG) trt_on = trait.OnOffTrait(hass, State("fan.bla", STATE_ON), BASIC_CONFIG)
@ -250,7 +257,7 @@ async def test_onoff_fan(hass):
async def test_onoff_light(hass): async def test_onoff_light(hass):
"""Test OnOff trait support for light domain.""" """Test OnOff trait support for light domain."""
assert helpers.get_google_type(light.DOMAIN, None) is not None assert helpers.get_google_type(light.DOMAIN, None) is not None
assert trait.OnOffTrait.supported(light.DOMAIN, 0, None) assert trait.OnOffTrait.supported(light.DOMAIN, 0, None, None)
trt_on = trait.OnOffTrait(hass, State("light.bla", STATE_ON), BASIC_CONFIG) trt_on = trait.OnOffTrait(hass, State("light.bla", STATE_ON), BASIC_CONFIG)
@ -276,7 +283,7 @@ async def test_onoff_light(hass):
async def test_onoff_media_player(hass): async def test_onoff_media_player(hass):
"""Test OnOff trait support for media_player domain.""" """Test OnOff trait support for media_player domain."""
assert helpers.get_google_type(media_player.DOMAIN, None) is not None assert helpers.get_google_type(media_player.DOMAIN, None) is not None
assert trait.OnOffTrait.supported(media_player.DOMAIN, 0, None) assert trait.OnOffTrait.supported(media_player.DOMAIN, 0, None, None)
trt_on = trait.OnOffTrait(hass, State("media_player.bla", STATE_ON), BASIC_CONFIG) trt_on = trait.OnOffTrait(hass, State("media_player.bla", STATE_ON), BASIC_CONFIG)
@ -303,7 +310,7 @@ async def test_onoff_media_player(hass):
async def test_onoff_humidifier(hass): async def test_onoff_humidifier(hass):
"""Test OnOff trait support for humidifier domain.""" """Test OnOff trait support for humidifier domain."""
assert helpers.get_google_type(humidifier.DOMAIN, None) is not None assert helpers.get_google_type(humidifier.DOMAIN, None) is not None
assert trait.OnOffTrait.supported(humidifier.DOMAIN, 0, None) assert trait.OnOffTrait.supported(humidifier.DOMAIN, 0, None, None)
trt_on = trait.OnOffTrait(hass, State("humidifier.bla", STATE_ON), BASIC_CONFIG) trt_on = trait.OnOffTrait(hass, State("humidifier.bla", STATE_ON), BASIC_CONFIG)
@ -330,7 +337,7 @@ async def test_onoff_humidifier(hass):
async def test_dock_vacuum(hass): async def test_dock_vacuum(hass):
"""Test dock trait support for vacuum domain.""" """Test dock trait support for vacuum domain."""
assert helpers.get_google_type(vacuum.DOMAIN, None) is not None assert helpers.get_google_type(vacuum.DOMAIN, None) is not None
assert trait.DockTrait.supported(vacuum.DOMAIN, 0, None) assert trait.DockTrait.supported(vacuum.DOMAIN, 0, None, None)
trt = trait.DockTrait(hass, State("vacuum.bla", vacuum.STATE_IDLE), BASIC_CONFIG) trt = trait.DockTrait(hass, State("vacuum.bla", vacuum.STATE_IDLE), BASIC_CONFIG)
@ -347,7 +354,7 @@ async def test_dock_vacuum(hass):
async def test_startstop_vacuum(hass): async def test_startstop_vacuum(hass):
"""Test startStop trait support for vacuum domain.""" """Test startStop trait support for vacuum domain."""
assert helpers.get_google_type(vacuum.DOMAIN, None) is not None assert helpers.get_google_type(vacuum.DOMAIN, None) is not None
assert trait.StartStopTrait.supported(vacuum.DOMAIN, 0, None) assert trait.StartStopTrait.supported(vacuum.DOMAIN, 0, None, None)
trt = trait.StartStopTrait( trt = trait.StartStopTrait(
hass, hass,
@ -387,7 +394,7 @@ async def test_startstop_vacuum(hass):
async def test_startstop_cover(hass): async def test_startstop_cover(hass):
"""Test startStop trait support for cover domain.""" """Test startStop trait support for cover domain."""
assert helpers.get_google_type(cover.DOMAIN, None) is not None assert helpers.get_google_type(cover.DOMAIN, None) is not None
assert trait.StartStopTrait.supported(cover.DOMAIN, cover.SUPPORT_STOP, None) assert trait.StartStopTrait.supported(cover.DOMAIN, cover.SUPPORT_STOP, None, None)
state = State( state = State(
"cover.bla", "cover.bla",
@ -447,11 +454,14 @@ async def test_startstop_cover_assumed(hass):
assert stop_calls[0].data == {ATTR_ENTITY_ID: "cover.bla"} assert stop_calls[0].data == {ATTR_ENTITY_ID: "cover.bla"}
async def test_color_setting_color_light(hass): @pytest.mark.parametrize("supported_color_modes", [["hs"], ["rgb"], ["xy"]])
async def test_color_setting_color_light(hass, supported_color_modes):
"""Test ColorSpectrum trait support for light domain.""" """Test ColorSpectrum trait support for light domain."""
assert helpers.get_google_type(light.DOMAIN, None) is not None assert helpers.get_google_type(light.DOMAIN, None) is not None
assert not trait.ColorSettingTrait.supported(light.DOMAIN, 0, None) assert not trait.ColorSettingTrait.supported(light.DOMAIN, 0, None, {})
assert trait.ColorSettingTrait.supported(light.DOMAIN, light.SUPPORT_COLOR, None) assert trait.ColorSettingTrait.supported(
light.DOMAIN, 0, None, {"supported_color_modes": supported_color_modes}
)
trt = trait.ColorSettingTrait( trt = trait.ColorSettingTrait(
hass, hass,
@ -461,7 +471,7 @@ async def test_color_setting_color_light(hass):
{ {
light.ATTR_HS_COLOR: (20, 94), light.ATTR_HS_COLOR: (20, 94),
light.ATTR_BRIGHTNESS: 200, light.ATTR_BRIGHTNESS: 200,
ATTR_SUPPORTED_FEATURES: light.SUPPORT_COLOR, "supported_color_modes": supported_color_modes,
}, },
), ),
BASIC_CONFIG, BASIC_CONFIG,
@ -507,9 +517,9 @@ async def test_color_setting_color_light(hass):
async def test_color_setting_temperature_light(hass): async def test_color_setting_temperature_light(hass):
"""Test ColorTemperature trait support for light domain.""" """Test ColorTemperature trait support for light domain."""
assert helpers.get_google_type(light.DOMAIN, None) is not None assert helpers.get_google_type(light.DOMAIN, None) is not None
assert not trait.ColorSettingTrait.supported(light.DOMAIN, 0, None) assert not trait.ColorSettingTrait.supported(light.DOMAIN, 0, None, {})
assert trait.ColorSettingTrait.supported( assert trait.ColorSettingTrait.supported(
light.DOMAIN, light.SUPPORT_COLOR_TEMP, None light.DOMAIN, 0, None, {"supported_color_modes": ["color_temp"]}
) )
trt = trait.ColorSettingTrait( trt = trait.ColorSettingTrait(
@ -521,7 +531,7 @@ async def test_color_setting_temperature_light(hass):
light.ATTR_MIN_MIREDS: 200, light.ATTR_MIN_MIREDS: 200,
light.ATTR_COLOR_TEMP: 300, light.ATTR_COLOR_TEMP: 300,
light.ATTR_MAX_MIREDS: 500, light.ATTR_MAX_MIREDS: 500,
ATTR_SUPPORTED_FEATURES: light.SUPPORT_COLOR_TEMP, "supported_color_modes": ["color_temp"],
}, },
), ),
BASIC_CONFIG, BASIC_CONFIG,
@ -560,9 +570,9 @@ async def test_color_setting_temperature_light(hass):
async def test_color_light_temperature_light_bad_temp(hass): async def test_color_light_temperature_light_bad_temp(hass):
"""Test ColorTemperature trait support for light domain.""" """Test ColorTemperature trait support for light domain."""
assert helpers.get_google_type(light.DOMAIN, None) is not None assert helpers.get_google_type(light.DOMAIN, None) is not None
assert not trait.ColorSettingTrait.supported(light.DOMAIN, 0, None) assert not trait.ColorSettingTrait.supported(light.DOMAIN, 0, None, {})
assert trait.ColorSettingTrait.supported( assert trait.ColorSettingTrait.supported(
light.DOMAIN, light.SUPPORT_COLOR_TEMP, None light.DOMAIN, 0, None, {"supported_color_modes": ["color_temp"]}
) )
trt = trait.ColorSettingTrait( trt = trait.ColorSettingTrait(
@ -585,7 +595,7 @@ async def test_color_light_temperature_light_bad_temp(hass):
async def test_light_modes(hass): async def test_light_modes(hass):
"""Test Light Mode trait.""" """Test Light Mode trait."""
assert helpers.get_google_type(light.DOMAIN, None) is not None assert helpers.get_google_type(light.DOMAIN, None) is not None
assert trait.ModesTrait.supported(light.DOMAIN, light.SUPPORT_EFFECT, None) assert trait.ModesTrait.supported(light.DOMAIN, light.SUPPORT_EFFECT, None, None)
trt = trait.ModesTrait( trt = trait.ModesTrait(
hass, hass,
@ -653,7 +663,7 @@ async def test_light_modes(hass):
async def test_scene_scene(hass): async def test_scene_scene(hass):
"""Test Scene trait support for scene domain.""" """Test Scene trait support for scene domain."""
assert helpers.get_google_type(scene.DOMAIN, None) is not None assert helpers.get_google_type(scene.DOMAIN, None) is not None
assert trait.SceneTrait.supported(scene.DOMAIN, 0, None) assert trait.SceneTrait.supported(scene.DOMAIN, 0, None, None)
trt = trait.SceneTrait(hass, State("scene.bla", scene.STATE), BASIC_CONFIG) trt = trait.SceneTrait(hass, State("scene.bla", scene.STATE), BASIC_CONFIG)
assert trt.sync_attributes() == {} assert trt.sync_attributes() == {}
@ -669,7 +679,7 @@ async def test_scene_scene(hass):
async def test_scene_script(hass): async def test_scene_script(hass):
"""Test Scene trait support for script domain.""" """Test Scene trait support for script domain."""
assert helpers.get_google_type(script.DOMAIN, None) is not None assert helpers.get_google_type(script.DOMAIN, None) is not None
assert trait.SceneTrait.supported(script.DOMAIN, 0, None) assert trait.SceneTrait.supported(script.DOMAIN, 0, None, None)
trt = trait.SceneTrait(hass, State("script.bla", STATE_OFF), BASIC_CONFIG) trt = trait.SceneTrait(hass, State("script.bla", STATE_OFF), BASIC_CONFIG)
assert trt.sync_attributes() == {} assert trt.sync_attributes() == {}
@ -689,7 +699,7 @@ async def test_scene_script(hass):
async def test_temperature_setting_climate_onoff(hass): async def test_temperature_setting_climate_onoff(hass):
"""Test TemperatureSetting trait support for climate domain - range.""" """Test TemperatureSetting trait support for climate domain - range."""
assert helpers.get_google_type(climate.DOMAIN, None) is not None assert helpers.get_google_type(climate.DOMAIN, None) is not None
assert trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None) assert trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None, None)
hass.config.units.temperature_unit = TEMP_FAHRENHEIT hass.config.units.temperature_unit = TEMP_FAHRENHEIT
@ -734,7 +744,7 @@ async def test_temperature_setting_climate_onoff(hass):
async def test_temperature_setting_climate_no_modes(hass): async def test_temperature_setting_climate_no_modes(hass):
"""Test TemperatureSetting trait support for climate domain not supporting any modes.""" """Test TemperatureSetting trait support for climate domain not supporting any modes."""
assert helpers.get_google_type(climate.DOMAIN, None) is not None assert helpers.get_google_type(climate.DOMAIN, None) is not None
assert trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None) assert trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None, None)
hass.config.units.temperature_unit = TEMP_CELSIUS hass.config.units.temperature_unit = TEMP_CELSIUS
@ -760,7 +770,7 @@ async def test_temperature_setting_climate_no_modes(hass):
async def test_temperature_setting_climate_range(hass): async def test_temperature_setting_climate_range(hass):
"""Test TemperatureSetting trait support for climate domain - range.""" """Test TemperatureSetting trait support for climate domain - range."""
assert helpers.get_google_type(climate.DOMAIN, None) is not None assert helpers.get_google_type(climate.DOMAIN, None) is not None
assert trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None) assert trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None, None)
hass.config.units.temperature_unit = TEMP_FAHRENHEIT hass.config.units.temperature_unit = TEMP_FAHRENHEIT
@ -842,7 +852,7 @@ async def test_temperature_setting_climate_range(hass):
async def test_temperature_setting_climate_setpoint(hass): async def test_temperature_setting_climate_setpoint(hass):
"""Test TemperatureSetting trait support for climate domain - setpoint.""" """Test TemperatureSetting trait support for climate domain - setpoint."""
assert helpers.get_google_type(climate.DOMAIN, None) is not None assert helpers.get_google_type(climate.DOMAIN, None) is not None
assert trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None) assert trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None, None)
hass.config.units.temperature_unit = TEMP_CELSIUS hass.config.units.temperature_unit = TEMP_CELSIUS
@ -947,7 +957,7 @@ async def test_temperature_setting_climate_setpoint_auto(hass):
async def test_humidity_setting_humidifier_setpoint(hass): async def test_humidity_setting_humidifier_setpoint(hass):
"""Test HumiditySetting trait support for humidifier domain - setpoint.""" """Test HumiditySetting trait support for humidifier domain - setpoint."""
assert helpers.get_google_type(humidifier.DOMAIN, None) is not None assert helpers.get_google_type(humidifier.DOMAIN, None) is not None
assert trait.HumiditySettingTrait.supported(humidifier.DOMAIN, 0, None) assert trait.HumiditySettingTrait.supported(humidifier.DOMAIN, 0, None, None)
trt = trait.HumiditySettingTrait( trt = trait.HumiditySettingTrait(
hass, hass,
@ -983,7 +993,7 @@ async def test_humidity_setting_humidifier_setpoint(hass):
async def test_lock_unlock_lock(hass): async def test_lock_unlock_lock(hass):
"""Test LockUnlock trait locking support for lock domain.""" """Test LockUnlock trait locking support for lock domain."""
assert helpers.get_google_type(lock.DOMAIN, None) is not None assert helpers.get_google_type(lock.DOMAIN, None) is not None
assert trait.LockUnlockTrait.supported(lock.DOMAIN, lock.SUPPORT_OPEN, None) assert trait.LockUnlockTrait.supported(lock.DOMAIN, lock.SUPPORT_OPEN, None, None)
assert trait.LockUnlockTrait.might_2fa(lock.DOMAIN, lock.SUPPORT_OPEN, None) assert trait.LockUnlockTrait.might_2fa(lock.DOMAIN, lock.SUPPORT_OPEN, None)
trt = trait.LockUnlockTrait( trt = trait.LockUnlockTrait(
@ -1007,7 +1017,7 @@ async def test_lock_unlock_lock(hass):
async def test_lock_unlock_unlock(hass): async def test_lock_unlock_unlock(hass):
"""Test LockUnlock trait unlocking support for lock domain.""" """Test LockUnlock trait unlocking support for lock domain."""
assert helpers.get_google_type(lock.DOMAIN, None) is not None assert helpers.get_google_type(lock.DOMAIN, None) is not None
assert trait.LockUnlockTrait.supported(lock.DOMAIN, lock.SUPPORT_OPEN, None) assert trait.LockUnlockTrait.supported(lock.DOMAIN, lock.SUPPORT_OPEN, None, None)
trt = trait.LockUnlockTrait( trt = trait.LockUnlockTrait(
hass, State("lock.front_door", lock.STATE_LOCKED), PIN_CONFIG hass, State("lock.front_door", lock.STATE_LOCKED), PIN_CONFIG
@ -1067,7 +1077,7 @@ async def test_lock_unlock_unlock(hass):
async def test_arm_disarm_arm_away(hass): async def test_arm_disarm_arm_away(hass):
"""Test ArmDisarm trait Arming support for alarm_control_panel domain.""" """Test ArmDisarm trait Arming support for alarm_control_panel domain."""
assert helpers.get_google_type(alarm_control_panel.DOMAIN, None) is not None assert helpers.get_google_type(alarm_control_panel.DOMAIN, None) is not None
assert trait.ArmDisArmTrait.supported(alarm_control_panel.DOMAIN, 0, None) assert trait.ArmDisArmTrait.supported(alarm_control_panel.DOMAIN, 0, None, None)
assert trait.ArmDisArmTrait.might_2fa(alarm_control_panel.DOMAIN, 0, None) assert trait.ArmDisArmTrait.might_2fa(alarm_control_panel.DOMAIN, 0, None)
trt = trait.ArmDisArmTrait( trt = trait.ArmDisArmTrait(
@ -1230,7 +1240,7 @@ async def test_arm_disarm_arm_away(hass):
async def test_arm_disarm_disarm(hass): async def test_arm_disarm_disarm(hass):
"""Test ArmDisarm trait Disarming support for alarm_control_panel domain.""" """Test ArmDisarm trait Disarming support for alarm_control_panel domain."""
assert helpers.get_google_type(alarm_control_panel.DOMAIN, None) is not None assert helpers.get_google_type(alarm_control_panel.DOMAIN, None) is not None
assert trait.ArmDisArmTrait.supported(alarm_control_panel.DOMAIN, 0, None) assert trait.ArmDisArmTrait.supported(alarm_control_panel.DOMAIN, 0, None, None)
assert trait.ArmDisArmTrait.might_2fa(alarm_control_panel.DOMAIN, 0, None) assert trait.ArmDisArmTrait.might_2fa(alarm_control_panel.DOMAIN, 0, None)
trt = trait.ArmDisArmTrait( trt = trait.ArmDisArmTrait(
@ -1376,7 +1386,7 @@ async def test_arm_disarm_disarm(hass):
async def test_fan_speed(hass): async def test_fan_speed(hass):
"""Test FanSpeed trait speed control support for fan domain.""" """Test FanSpeed trait speed control support for fan domain."""
assert helpers.get_google_type(fan.DOMAIN, None) is not None assert helpers.get_google_type(fan.DOMAIN, None) is not None
assert trait.FanSpeedTrait.supported(fan.DOMAIN, fan.SUPPORT_SET_SPEED, None) assert trait.FanSpeedTrait.supported(fan.DOMAIN, fan.SUPPORT_SET_SPEED, None, None)
trt = trait.FanSpeedTrait( trt = trait.FanSpeedTrait(
hass, hass,
@ -1468,7 +1478,9 @@ async def test_fan_speed(hass):
async def test_climate_fan_speed(hass): async def test_climate_fan_speed(hass):
"""Test FanSpeed trait speed control support for climate domain.""" """Test FanSpeed trait speed control support for climate domain."""
assert helpers.get_google_type(climate.DOMAIN, None) is not None assert helpers.get_google_type(climate.DOMAIN, None) is not None
assert trait.FanSpeedTrait.supported(climate.DOMAIN, climate.SUPPORT_FAN_MODE, None) assert trait.FanSpeedTrait.supported(
climate.DOMAIN, climate.SUPPORT_FAN_MODE, None, None
)
trt = trait.FanSpeedTrait( trt = trait.FanSpeedTrait(
hass, hass,
@ -1529,7 +1541,7 @@ async def test_inputselector(hass):
"""Test input selector trait.""" """Test input selector trait."""
assert helpers.get_google_type(media_player.DOMAIN, None) is not None assert helpers.get_google_type(media_player.DOMAIN, None) is not None
assert trait.InputSelectorTrait.supported( assert trait.InputSelectorTrait.supported(
media_player.DOMAIN, media_player.SUPPORT_SELECT_SOURCE, None media_player.DOMAIN, media_player.SUPPORT_SELECT_SOURCE, None, None
) )
trt = trait.InputSelectorTrait( trt = trait.InputSelectorTrait(
@ -1686,7 +1698,7 @@ async def test_inputselector_nextprev_invalid(hass, sources, source):
async def test_modes_input_select(hass): async def test_modes_input_select(hass):
"""Test Input Select Mode trait.""" """Test Input Select Mode trait."""
assert helpers.get_google_type(input_select.DOMAIN, None) is not None assert helpers.get_google_type(input_select.DOMAIN, None) is not None
assert trait.ModesTrait.supported(input_select.DOMAIN, None, None) assert trait.ModesTrait.supported(input_select.DOMAIN, None, None, None)
trt = trait.ModesTrait( trt = trait.ModesTrait(
hass, hass,
@ -1762,7 +1774,9 @@ async def test_modes_input_select(hass):
async def test_modes_humidifier(hass): async def test_modes_humidifier(hass):
"""Test Humidifier Mode trait.""" """Test Humidifier Mode trait."""
assert helpers.get_google_type(humidifier.DOMAIN, None) is not None assert helpers.get_google_type(humidifier.DOMAIN, None) is not None
assert trait.ModesTrait.supported(humidifier.DOMAIN, humidifier.SUPPORT_MODES, None) assert trait.ModesTrait.supported(
humidifier.DOMAIN, humidifier.SUPPORT_MODES, None, None
)
trt = trait.ModesTrait( trt = trait.ModesTrait(
hass, hass,
@ -1840,7 +1854,7 @@ async def test_sound_modes(hass):
"""Test Mode trait.""" """Test Mode trait."""
assert helpers.get_google_type(media_player.DOMAIN, None) is not None assert helpers.get_google_type(media_player.DOMAIN, None) is not None
assert trait.ModesTrait.supported( assert trait.ModesTrait.supported(
media_player.DOMAIN, media_player.SUPPORT_SELECT_SOUND_MODE, None media_player.DOMAIN, media_player.SUPPORT_SELECT_SOUND_MODE, None, None
) )
trt = trait.ModesTrait( trt = trait.ModesTrait(
@ -1914,7 +1928,7 @@ async def test_openclose_cover(hass):
"""Test OpenClose trait support for cover domain.""" """Test OpenClose trait support for cover domain."""
assert helpers.get_google_type(cover.DOMAIN, None) is not None assert helpers.get_google_type(cover.DOMAIN, None) is not None
assert trait.OpenCloseTrait.supported( assert trait.OpenCloseTrait.supported(
cover.DOMAIN, cover.SUPPORT_SET_POSITION, None cover.DOMAIN, cover.SUPPORT_SET_POSITION, None, None
) )
trt = trait.OpenCloseTrait( trt = trait.OpenCloseTrait(
@ -1951,7 +1965,7 @@ async def test_openclose_cover_unknown_state(hass):
"""Test OpenClose trait support for cover domain with unknown state.""" """Test OpenClose trait support for cover domain with unknown state."""
assert helpers.get_google_type(cover.DOMAIN, None) is not None assert helpers.get_google_type(cover.DOMAIN, None) is not None
assert trait.OpenCloseTrait.supported( assert trait.OpenCloseTrait.supported(
cover.DOMAIN, cover.SUPPORT_SET_POSITION, None cover.DOMAIN, cover.SUPPORT_SET_POSITION, None, None
) )
# No state # No state
@ -1981,7 +1995,7 @@ async def test_openclose_cover_assumed_state(hass):
"""Test OpenClose trait support for cover domain.""" """Test OpenClose trait support for cover domain."""
assert helpers.get_google_type(cover.DOMAIN, None) is not None assert helpers.get_google_type(cover.DOMAIN, None) is not None
assert trait.OpenCloseTrait.supported( assert trait.OpenCloseTrait.supported(
cover.DOMAIN, cover.SUPPORT_SET_POSITION, None cover.DOMAIN, cover.SUPPORT_SET_POSITION, None, None
) )
trt = trait.OpenCloseTrait( trt = trait.OpenCloseTrait(
@ -2010,7 +2024,7 @@ async def test_openclose_cover_assumed_state(hass):
async def test_openclose_cover_query_only(hass): async def test_openclose_cover_query_only(hass):
"""Test OpenClose trait support for cover domain.""" """Test OpenClose trait support for cover domain."""
assert helpers.get_google_type(cover.DOMAIN, None) is not None assert helpers.get_google_type(cover.DOMAIN, None) is not None
assert trait.OpenCloseTrait.supported(cover.DOMAIN, 0, None) assert trait.OpenCloseTrait.supported(cover.DOMAIN, 0, None, None)
state = State( state = State(
"cover.bla", "cover.bla",
@ -2034,7 +2048,7 @@ async def test_openclose_cover_no_position(hass):
"""Test OpenClose trait support for cover domain.""" """Test OpenClose trait support for cover domain."""
assert helpers.get_google_type(cover.DOMAIN, None) is not None assert helpers.get_google_type(cover.DOMAIN, None) is not None
assert trait.OpenCloseTrait.supported( assert trait.OpenCloseTrait.supported(
cover.DOMAIN, cover.SUPPORT_OPEN | cover.SUPPORT_CLOSE, None cover.DOMAIN, cover.SUPPORT_OPEN | cover.SUPPORT_CLOSE, None, None
) )
state = State( state = State(
@ -2091,7 +2105,7 @@ async def test_openclose_cover_secure(hass, device_class):
"""Test OpenClose trait support for cover domain.""" """Test OpenClose trait support for cover domain."""
assert helpers.get_google_type(cover.DOMAIN, device_class) is not None assert helpers.get_google_type(cover.DOMAIN, device_class) is not None
assert trait.OpenCloseTrait.supported( assert trait.OpenCloseTrait.supported(
cover.DOMAIN, cover.SUPPORT_SET_POSITION, device_class cover.DOMAIN, cover.SUPPORT_SET_POSITION, device_class, None
) )
assert trait.OpenCloseTrait.might_2fa( assert trait.OpenCloseTrait.might_2fa(
cover.DOMAIN, cover.SUPPORT_SET_POSITION, device_class cover.DOMAIN, cover.SUPPORT_SET_POSITION, device_class
@ -2158,7 +2172,7 @@ async def test_openclose_cover_secure(hass, device_class):
async def test_openclose_binary_sensor(hass, device_class): async def test_openclose_binary_sensor(hass, device_class):
"""Test OpenClose trait support for binary_sensor domain.""" """Test OpenClose trait support for binary_sensor domain."""
assert helpers.get_google_type(binary_sensor.DOMAIN, device_class) is not None assert helpers.get_google_type(binary_sensor.DOMAIN, device_class) is not None
assert trait.OpenCloseTrait.supported(binary_sensor.DOMAIN, 0, device_class) assert trait.OpenCloseTrait.supported(binary_sensor.DOMAIN, 0, device_class, None)
trt = trait.OpenCloseTrait( trt = trait.OpenCloseTrait(
hass, hass,
@ -2191,9 +2205,7 @@ async def test_volume_media_player(hass):
"""Test volume trait support for media player domain.""" """Test volume trait support for media player domain."""
assert helpers.get_google_type(media_player.DOMAIN, None) is not None assert helpers.get_google_type(media_player.DOMAIN, None) is not None
assert trait.VolumeTrait.supported( assert trait.VolumeTrait.supported(
media_player.DOMAIN, media_player.DOMAIN, media_player.SUPPORT_VOLUME_SET, None, None
media_player.SUPPORT_VOLUME_SET,
None,
) )
trt = trait.VolumeTrait( trt = trait.VolumeTrait(
@ -2244,9 +2256,7 @@ async def test_volume_media_player(hass):
async def test_volume_media_player_relative(hass): async def test_volume_media_player_relative(hass):
"""Test volume trait support for relative-volume-only media players.""" """Test volume trait support for relative-volume-only media players."""
assert trait.VolumeTrait.supported( assert trait.VolumeTrait.supported(
media_player.DOMAIN, media_player.DOMAIN, media_player.SUPPORT_VOLUME_STEP, None, None
media_player.SUPPORT_VOLUME_STEP,
None,
) )
trt = trait.VolumeTrait( trt = trait.VolumeTrait(
hass, hass,
@ -2314,6 +2324,7 @@ async def test_media_player_mute(hass):
media_player.DOMAIN, media_player.DOMAIN,
media_player.SUPPORT_VOLUME_STEP | media_player.SUPPORT_VOLUME_MUTE, media_player.SUPPORT_VOLUME_STEP | media_player.SUPPORT_VOLUME_MUTE,
None, None,
None,
) )
trt = trait.VolumeTrait( trt = trait.VolumeTrait(
hass, hass,
@ -2376,10 +2387,10 @@ async def test_temperature_setting_sensor(hass):
is not None is not None
) )
assert not trait.TemperatureSettingTrait.supported( assert not trait.TemperatureSettingTrait.supported(
sensor.DOMAIN, 0, sensor.DEVICE_CLASS_HUMIDITY sensor.DOMAIN, 0, sensor.DEVICE_CLASS_HUMIDITY, None
) )
assert trait.TemperatureSettingTrait.supported( assert trait.TemperatureSettingTrait.supported(
sensor.DOMAIN, 0, sensor.DEVICE_CLASS_TEMPERATURE sensor.DOMAIN, 0, sensor.DEVICE_CLASS_TEMPERATURE, None
) )
@ -2422,10 +2433,10 @@ async def test_humidity_setting_sensor(hass):
helpers.get_google_type(sensor.DOMAIN, sensor.DEVICE_CLASS_HUMIDITY) is not None helpers.get_google_type(sensor.DOMAIN, sensor.DEVICE_CLASS_HUMIDITY) is not None
) )
assert not trait.HumiditySettingTrait.supported( assert not trait.HumiditySettingTrait.supported(
sensor.DOMAIN, 0, sensor.DEVICE_CLASS_TEMPERATURE sensor.DOMAIN, 0, sensor.DEVICE_CLASS_TEMPERATURE, None
) )
assert trait.HumiditySettingTrait.supported( assert trait.HumiditySettingTrait.supported(
sensor.DOMAIN, 0, sensor.DEVICE_CLASS_HUMIDITY sensor.DOMAIN, 0, sensor.DEVICE_CLASS_HUMIDITY, None
) )
@ -2456,7 +2467,9 @@ async def test_transport_control(hass):
assert helpers.get_google_type(media_player.DOMAIN, None) is not None assert helpers.get_google_type(media_player.DOMAIN, None) is not None
for feature in trait.MEDIA_COMMAND_SUPPORT_MAPPING.values(): for feature in trait.MEDIA_COMMAND_SUPPORT_MAPPING.values():
assert trait.TransportControlTrait.supported(media_player.DOMAIN, feature, None) assert trait.TransportControlTrait.supported(
media_player.DOMAIN, feature, None, None
)
now = datetime(2020, 1, 1) now = datetime(2020, 1, 1)
@ -2586,7 +2599,7 @@ async def test_media_state(hass, state):
assert helpers.get_google_type(media_player.DOMAIN, None) is not None assert helpers.get_google_type(media_player.DOMAIN, None) is not None
assert trait.TransportControlTrait.supported( assert trait.TransportControlTrait.supported(
media_player.DOMAIN, media_player.SUPPORT_PLAY, None media_player.DOMAIN, media_player.SUPPORT_PLAY, None, None
) )
trt = trait.MediaStateTrait( trt = trait.MediaStateTrait(