"""Test Alexa capabilities.""" import pytest from homeassistant.const import ( ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS, STATE_LOCKED, STATE_UNLOCKED, STATE_UNKNOWN, STATE_UNAVAILABLE, ) from homeassistant.components.climate import const as climate from homeassistant.components.alexa import smart_home from homeassistant.components.alexa.errors import UnsupportedProperty from tests.common import async_mock_service from . import ( DEFAULT_CONFIG, get_new_request, assert_request_calls_service, assert_request_fails, reported_properties, ) @pytest.mark.parametrize("result,adjust", [(25, "-5"), (35, "5"), (0, "-80")]) async def test_api_adjust_brightness(hass, result, adjust): """Test api adjust brightness process.""" request = get_new_request( "Alexa.BrightnessController", "AdjustBrightness", "light#test" ) # add payload request["directive"]["payload"]["brightnessDelta"] = adjust # setup test devices hass.states.async_set( "light.test", "off", {"friendly_name": "Test light", "brightness": "77"} ) call_light = async_mock_service(hass, "light", "turn_on") msg = await smart_home.async_handle_message(hass, DEFAULT_CONFIG, request) await hass.async_block_till_done() assert "event" in msg msg = msg["event"] assert len(call_light) == 1 assert call_light[0].data["entity_id"] == "light.test" assert call_light[0].data["brightness_pct"] == result assert msg["header"]["name"] == "Response" async def test_api_set_color_rgb(hass): """Test api set color process.""" request = get_new_request("Alexa.ColorController", "SetColor", "light#test") # add payload request["directive"]["payload"]["color"] = { "hue": "120", "saturation": "0.612", "brightness": "0.342", } # setup test devices hass.states.async_set( "light.test", "off", {"friendly_name": "Test light", "supported_features": 16} ) call_light = async_mock_service(hass, "light", "turn_on") msg = await smart_home.async_handle_message(hass, DEFAULT_CONFIG, request) await hass.async_block_till_done() assert "event" in msg msg = msg["event"] assert len(call_light) == 1 assert call_light[0].data["entity_id"] == "light.test" assert call_light[0].data["rgb_color"] == (33, 87, 33) assert msg["header"]["name"] == "Response" async def test_api_set_color_temperature(hass): """Test api set color temperature process.""" request = get_new_request( "Alexa.ColorTemperatureController", "SetColorTemperature", "light#test" ) # add payload request["directive"]["payload"]["colorTemperatureInKelvin"] = "7500" # setup test devices hass.states.async_set("light.test", "off", {"friendly_name": "Test light"}) call_light = async_mock_service(hass, "light", "turn_on") msg = await smart_home.async_handle_message(hass, DEFAULT_CONFIG, request) await hass.async_block_till_done() assert "event" in msg msg = msg["event"] assert len(call_light) == 1 assert call_light[0].data["entity_id"] == "light.test" assert call_light[0].data["kelvin"] == 7500 assert msg["header"]["name"] == "Response" @pytest.mark.parametrize("result,initial", [(383, "333"), (500, "500")]) async def test_api_decrease_color_temp(hass, result, initial): """Test api decrease color temp process.""" request = get_new_request( "Alexa.ColorTemperatureController", "DecreaseColorTemperature", "light#test" ) # setup test devices hass.states.async_set( "light.test", "off", {"friendly_name": "Test light", "color_temp": initial, "max_mireds": 500}, ) call_light = async_mock_service(hass, "light", "turn_on") msg = await smart_home.async_handle_message(hass, DEFAULT_CONFIG, request) await hass.async_block_till_done() assert "event" in msg msg = msg["event"] assert len(call_light) == 1 assert call_light[0].data["entity_id"] == "light.test" assert call_light[0].data["color_temp"] == result assert msg["header"]["name"] == "Response" @pytest.mark.parametrize("result,initial", [(283, "333"), (142, "142")]) async def test_api_increase_color_temp(hass, result, initial): """Test api increase color temp process.""" request = get_new_request( "Alexa.ColorTemperatureController", "IncreaseColorTemperature", "light#test" ) # setup test devices hass.states.async_set( "light.test", "off", {"friendly_name": "Test light", "color_temp": initial, "min_mireds": 142}, ) call_light = async_mock_service(hass, "light", "turn_on") msg = await smart_home.async_handle_message(hass, DEFAULT_CONFIG, request) await hass.async_block_till_done() assert "event" in msg msg = msg["event"] assert len(call_light) == 1 assert call_light[0].data["entity_id"] == "light.test" assert call_light[0].data["color_temp"] == result assert msg["header"]["name"] == "Response" @pytest.mark.parametrize( "domain,payload,source_list,idx", [ ("media_player", "GAME CONSOLE", ["tv", "game console"], 1), ("media_player", "SATELLITE TV", ["satellite-tv", "game console"], 0), ("media_player", "SATELLITE TV", ["satellite_tv", "game console"], 0), ("media_player", "BAD DEVICE", ["satellite_tv", "game console"], None), ], ) async def test_api_select_input(hass, domain, payload, source_list, idx): """Test api set input process.""" hass.states.async_set( "media_player.test", "off", { "friendly_name": "Test media player", "source": "unknown", "source_list": source_list, }, ) # test where no source matches if idx is None: await assert_request_fails( "Alexa.InputController", "SelectInput", "media_player#test", "media_player.select_source", hass, payload={"input": payload}, ) return call, _ = await assert_request_calls_service( "Alexa.InputController", "SelectInput", "media_player#test", "media_player.select_source", hass, payload={"input": payload}, ) assert call.data["source"] == source_list[idx] async def test_report_lock_state(hass): """Test LockController implements lockState property.""" hass.states.async_set("lock.locked", STATE_LOCKED, {}) hass.states.async_set("lock.unlocked", STATE_UNLOCKED, {}) hass.states.async_set("lock.unknown", STATE_UNKNOWN, {}) properties = await reported_properties(hass, "lock.locked") properties.assert_equal("Alexa.LockController", "lockState", "LOCKED") properties = await reported_properties(hass, "lock.unlocked") properties.assert_equal("Alexa.LockController", "lockState", "UNLOCKED") properties = await reported_properties(hass, "lock.unknown") properties.assert_equal("Alexa.LockController", "lockState", "JAMMED") async def test_report_dimmable_light_state(hass): """Test BrightnessController reports brightness correctly.""" hass.states.async_set( "light.test_on", "on", {"friendly_name": "Test light On", "brightness": 128, "supported_features": 1}, ) hass.states.async_set( "light.test_off", "off", {"friendly_name": "Test light Off", "supported_features": 1}, ) properties = await reported_properties(hass, "light.test_on") properties.assert_equal("Alexa.BrightnessController", "brightness", 50) properties = await reported_properties(hass, "light.test_off") properties.assert_equal("Alexa.BrightnessController", "brightness", 0) async def test_report_colored_light_state(hass): """Test ColorController reports color correctly.""" hass.states.async_set( "light.test_on", "on", { "friendly_name": "Test light On", "hs_color": (180, 75), "brightness": 128, "supported_features": 17, }, ) hass.states.async_set( "light.test_off", "off", {"friendly_name": "Test light Off", "supported_features": 17}, ) properties = await reported_properties(hass, "light.test_on") properties.assert_equal( "Alexa.ColorController", "color", {"hue": 180, "saturation": 0.75, "brightness": 128 / 255.0}, ) properties = await reported_properties(hass, "light.test_off") properties.assert_equal( "Alexa.ColorController", "color", {"hue": 0, "saturation": 0, "brightness": 0} ) async def test_report_colored_temp_light_state(hass): """Test ColorTemperatureController reports color temp correctly.""" hass.states.async_set( "light.test_on", "on", {"friendly_name": "Test light On", "color_temp": 240, "supported_features": 2}, ) hass.states.async_set( "light.test_off", "off", {"friendly_name": "Test light Off", "supported_features": 2}, ) properties = await reported_properties(hass, "light.test_on") properties.assert_equal( "Alexa.ColorTemperatureController", "colorTemperatureInKelvin", 4166 ) properties = await reported_properties(hass, "light.test_off") properties.assert_equal( "Alexa.ColorTemperatureController", "colorTemperatureInKelvin", 0 ) async def test_report_fan_speed_state(hass): """Test PercentageController reports fan speed correctly.""" hass.states.async_set( "fan.off", "off", {"friendly_name": "Off fan", "speed": "off", "supported_features": 1}, ) hass.states.async_set( "fan.low_speed", "on", {"friendly_name": "Low speed fan", "speed": "low", "supported_features": 1}, ) hass.states.async_set( "fan.medium_speed", "on", { "friendly_name": "Medium speed fan", "speed": "medium", "supported_features": 1, }, ) hass.states.async_set( "fan.high_speed", "on", {"friendly_name": "High speed fan", "speed": "high", "supported_features": 1}, ) properties = await reported_properties(hass, "fan.off") properties.assert_equal("Alexa.PercentageController", "percentage", 0) properties = await reported_properties(hass, "fan.low_speed") properties.assert_equal("Alexa.PercentageController", "percentage", 33) properties = await reported_properties(hass, "fan.medium_speed") properties.assert_equal("Alexa.PercentageController", "percentage", 66) properties = await reported_properties(hass, "fan.high_speed") properties.assert_equal("Alexa.PercentageController", "percentage", 100) async def test_report_cover_percentage_state(hass): """Test PercentageController reports cover percentage correctly.""" hass.states.async_set( "cover.fully_open", "open", { "friendly_name": "Fully open cover", "current_position": 100, "supported_features": 15, }, ) hass.states.async_set( "cover.half_open", "open", { "friendly_name": "Half open cover", "current_position": 50, "supported_features": 15, }, ) hass.states.async_set( "cover.closed", "closed", { "friendly_name": "Closed cover", "current_position": 0, "supported_features": 15, }, ) properties = await reported_properties(hass, "cover.fully_open") properties.assert_equal("Alexa.PercentageController", "percentage", 100) properties = await reported_properties(hass, "cover.half_open") properties.assert_equal("Alexa.PercentageController", "percentage", 50) properties = await reported_properties(hass, "cover.closed") properties.assert_equal("Alexa.PercentageController", "percentage", 0) async def test_report_climate_state(hass): """Test ThermostatController reports state correctly.""" for auto_modes in (climate.HVAC_MODE_AUTO, climate.HVAC_MODE_HEAT_COOL): hass.states.async_set( "climate.downstairs", auto_modes, { "friendly_name": "Climate Downstairs", "supported_features": 91, climate.ATTR_CURRENT_TEMPERATURE: 34, ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS, }, ) properties = await reported_properties(hass, "climate.downstairs") properties.assert_equal("Alexa.ThermostatController", "thermostatMode", "AUTO") properties.assert_equal( "Alexa.TemperatureSensor", "temperature", {"value": 34.0, "scale": "CELSIUS"}, ) for off_modes in ( climate.HVAC_MODE_OFF, climate.HVAC_MODE_FAN_ONLY, climate.HVAC_MODE_DRY, ): hass.states.async_set( "climate.downstairs", off_modes, { "friendly_name": "Climate Downstairs", "supported_features": 91, climate.ATTR_CURRENT_TEMPERATURE: 34, ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS, }, ) properties = await reported_properties(hass, "climate.downstairs") properties.assert_equal("Alexa.ThermostatController", "thermostatMode", "OFF") properties.assert_equal( "Alexa.TemperatureSensor", "temperature", {"value": 34.0, "scale": "CELSIUS"}, ) hass.states.async_set( "climate.heat", "heat", { "friendly_name": "Climate Heat", "supported_features": 91, climate.ATTR_CURRENT_TEMPERATURE: 34, ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS, }, ) properties = await reported_properties(hass, "climate.heat") properties.assert_equal("Alexa.ThermostatController", "thermostatMode", "HEAT") properties.assert_equal( "Alexa.TemperatureSensor", "temperature", {"value": 34.0, "scale": "CELSIUS"} ) hass.states.async_set( "climate.cool", "cool", { "friendly_name": "Climate Cool", "supported_features": 91, climate.ATTR_CURRENT_TEMPERATURE: 34, ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS, }, ) properties = await reported_properties(hass, "climate.cool") properties.assert_equal("Alexa.ThermostatController", "thermostatMode", "COOL") properties.assert_equal( "Alexa.TemperatureSensor", "temperature", {"value": 34.0, "scale": "CELSIUS"} ) hass.states.async_set( "climate.unavailable", "unavailable", {"friendly_name": "Climate Unavailable", "supported_features": 91}, ) properties = await reported_properties(hass, "climate.unavailable") properties.assert_not_has_property("Alexa.ThermostatController", "thermostatMode") hass.states.async_set( "climate.unsupported", "blablabla", { "friendly_name": "Climate Unsupported", "supported_features": 91, climate.ATTR_CURRENT_TEMPERATURE: 34, ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS, }, ) with pytest.raises(UnsupportedProperty): properties = await reported_properties(hass, "climate.unsupported") properties.assert_not_has_property( "Alexa.ThermostatController", "thermostatMode" ) properties.assert_equal( "Alexa.TemperatureSensor", "temperature", {"value": 34.0, "scale": "CELSIUS"}, ) async def test_temperature_sensor_sensor(hass): """Test TemperatureSensor reports sensor temperature correctly.""" for bad_value in (STATE_UNKNOWN, STATE_UNAVAILABLE, "not-number"): hass.states.async_set( "sensor.temp_living_room", bad_value, {ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}, ) properties = await reported_properties(hass, "sensor.temp_living_room") properties.assert_not_has_property("Alexa.TemperatureSensor", "temperature") hass.states.async_set( "sensor.temp_living_room", "34", {ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS} ) properties = await reported_properties(hass, "sensor.temp_living_room") properties.assert_equal( "Alexa.TemperatureSensor", "temperature", {"value": 34.0, "scale": "CELSIUS"} ) async def test_temperature_sensor_climate(hass): """Test TemperatureSensor reports climate temperature correctly.""" for bad_value in (STATE_UNKNOWN, STATE_UNAVAILABLE, "not-number"): hass.states.async_set( "climate.downstairs", climate.HVAC_MODE_HEAT, {climate.ATTR_CURRENT_TEMPERATURE: bad_value}, ) properties = await reported_properties(hass, "climate.downstairs") properties.assert_not_has_property("Alexa.TemperatureSensor", "temperature") hass.states.async_set( "climate.downstairs", climate.HVAC_MODE_HEAT, {climate.ATTR_CURRENT_TEMPERATURE: 34}, ) properties = await reported_properties(hass, "climate.downstairs") properties.assert_equal( "Alexa.TemperatureSensor", "temperature", {"value": 34.0, "scale": "CELSIUS"} )