From ecabf92504ec693d658994743b5d8fbad67b365a Mon Sep 17 00:00:00 2001 From: Penny Wood Date: Sat, 23 Mar 2019 04:42:56 +0800 Subject: [PATCH] Update trait to support auto without ranges. (#21847) --- .../components/google_assistant/trait.py | 52 ++++++++++------ .../google_assistant/test_google_assistant.py | 2 + .../components/google_assistant/test_trait.py | 59 +++++++++++++++++-- 3 files changed, 91 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/google_assistant/trait.py b/homeassistant/components/google_assistant/trait.py index f5b959285db..26d1ccc2088 100644 --- a/homeassistant/components/google_assistant/trait.py +++ b/homeassistant/components/google_assistant/trait.py @@ -583,15 +583,24 @@ class TemperatureSettingTrait(_Trait): if current_humidity is not None: response['thermostatHumidityAmbient'] = current_humidity - if (operation == climate.STATE_AUTO and - climate.ATTR_TARGET_TEMP_HIGH in attrs and - climate.ATTR_TARGET_TEMP_LOW in attrs): - response['thermostatTemperatureSetpointHigh'] = \ - round(temp_util.convert(attrs[climate.ATTR_TARGET_TEMP_HIGH], - unit, TEMP_CELSIUS), 1) - response['thermostatTemperatureSetpointLow'] = \ - round(temp_util.convert(attrs[climate.ATTR_TARGET_TEMP_LOW], - unit, TEMP_CELSIUS), 1) + if operation == climate.STATE_AUTO: + if (supported & climate.SUPPORT_TARGET_TEMPERATURE_HIGH and + supported & climate.SUPPORT_TARGET_TEMPERATURE_LOW): + response['thermostatTemperatureSetpointHigh'] = \ + round(temp_util.convert( + attrs[climate.ATTR_TARGET_TEMP_HIGH], + unit, TEMP_CELSIUS), 1) + response['thermostatTemperatureSetpointLow'] = \ + round(temp_util.convert( + attrs[climate.ATTR_TARGET_TEMP_LOW], + unit, TEMP_CELSIUS), 1) + else: + target_temp = attrs.get(ATTR_TEMPERATURE) + if target_temp is not None: + target_temp = round( + temp_util.convert(target_temp, unit, TEMP_CELSIUS), 1) + response['thermostatTemperatureSetpointHigh'] = target_temp + response['thermostatTemperatureSetpointLow'] = target_temp else: target_temp = attrs.get(ATTR_TEMPERATURE) if target_temp is not None: @@ -651,12 +660,21 @@ class TemperatureSettingTrait(_Trait): "Lower bound for temperature range should be between " "{} and {}".format(min_temp, max_temp)) + supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES) + svc_data = { + ATTR_ENTITY_ID: self.state.entity_id, + } + + if(supported & climate.SUPPORT_TARGET_TEMPERATURE_HIGH and + supported & climate.SUPPORT_TARGET_TEMPERATURE_LOW): + svc_data[climate.ATTR_TARGET_TEMP_HIGH] = temp_high + svc_data[climate.ATTR_TARGET_TEMP_LOW] = temp_low + else: + svc_data[ATTR_TEMPERATURE] = (temp_high + temp_low) / 2 + await self.hass.services.async_call( - climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, { - ATTR_ENTITY_ID: self.state.entity_id, - climate.ATTR_TARGET_TEMP_HIGH: temp_high, - climate.ATTR_TARGET_TEMP_LOW: temp_low, - }, blocking=True, context=data.context) + climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, svc_data, + blocking=True, context=data.context) elif command == COMMAND_THERMOSTAT_SET_MODE: target_mode = params['thermostatMode'] @@ -669,10 +687,8 @@ class TemperatureSettingTrait(_Trait): (SERVICE_TURN_ON if target_mode == STATE_ON else SERVICE_TURN_OFF), - { - ATTR_ENTITY_ID: self.state.entity_id, - climate.ATTR_OPERATION_MODE: target_mode, - }, blocking=True, context=data.context) + {ATTR_ENTITY_ID: self.state.entity_id}, + blocking=True, context=data.context) elif supported & climate.SUPPORT_OPERATION_MODE: await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_OPERATION_MODE, { diff --git a/tests/components/google_assistant/test_google_assistant.py b/tests/components/google_assistant/test_google_assistant.py index fbaf1b47898..69964a11fdc 100644 --- a/tests/components/google_assistant/test_google_assistant.py +++ b/tests/components/google_assistant/test_google_assistant.py @@ -107,6 +107,8 @@ def hass_fixture(loop, hass): return hass +# pylint: disable=redefined-outer-name + @asyncio.coroutine def test_sync_request(hass_fixture, assistant_client, auth_header): diff --git a/tests/components/google_assistant/test_trait.py b/tests/components/google_assistant/test_trait.py index 3af60e2f014..9d067f3314f 100644 --- a/tests/components/google_assistant/test_trait.py +++ b/tests/components/google_assistant/test_trait.py @@ -649,7 +649,9 @@ async def test_temperature_setting_climate_onoff(hass): trt = trait.TemperatureSettingTrait(hass, State( 'climate.bla', climate.STATE_AUTO, { ATTR_SUPPORTED_FEATURES: ( - climate.SUPPORT_OPERATION_MODE | climate.SUPPORT_ON_OFF), + climate.SUPPORT_OPERATION_MODE | climate.SUPPORT_ON_OFF | + climate.SUPPORT_TARGET_TEMPERATURE_HIGH | + climate.SUPPORT_TARGET_TEMPERATURE_LOW), climate.ATTR_OPERATION_MODE: climate.STATE_COOL, climate.ATTR_OPERATION_LIST: [ climate.STATE_COOL, @@ -692,7 +694,10 @@ async def test_temperature_setting_climate_range(hass): 'climate.bla', climate.STATE_AUTO, { climate.ATTR_CURRENT_TEMPERATURE: 70, climate.ATTR_CURRENT_HUMIDITY: 25, - ATTR_SUPPORTED_FEATURES: climate.SUPPORT_OPERATION_MODE, + ATTR_SUPPORTED_FEATURES: + climate.SUPPORT_OPERATION_MODE | + climate.SUPPORT_TARGET_TEMPERATURE_HIGH | + climate.SUPPORT_TARGET_TEMPERATURE_LOW, climate.ATTR_OPERATION_MODE: climate.STATE_AUTO, climate.ATTR_OPERATION_LIST: [ STATE_OFF, @@ -716,7 +721,6 @@ async def test_temperature_setting_climate_range(hass): 'thermostatTemperatureSetpointLow': 18.3, 'thermostatTemperatureSetpointHigh': 23.9, } - assert trt.can_execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, {}) assert trt.can_execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SET_RANGE, {}) assert trt.can_execute(trait.COMMAND_THERMOSTAT_SET_MODE, {}) @@ -785,7 +789,6 @@ async def test_temperature_setting_climate_setpoint(hass): 'thermostatTemperatureSetpoint': 18, } assert trt.can_execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, {}) - assert trt.can_execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SET_RANGE, {}) assert trt.can_execute(trait.COMMAND_THERMOSTAT_SET_MODE, {}) calls = async_mock_service( @@ -806,6 +809,54 @@ async def test_temperature_setting_climate_setpoint(hass): } +async def test_temperature_setting_climate_setpoint_auto(hass): + """ + Test TemperatureSetting trait support for climate domain. + + Setpoint in auto mode. + """ + hass.config.units.temperature_unit = TEMP_CELSIUS + + trt = trait.TemperatureSettingTrait(hass, State( + 'climate.bla', climate.STATE_AUTO, { + ATTR_SUPPORTED_FEATURES: ( + climate.SUPPORT_OPERATION_MODE | climate.SUPPORT_ON_OFF), + climate.ATTR_OPERATION_MODE: climate.STATE_AUTO, + climate.ATTR_OPERATION_LIST: [ + STATE_OFF, + climate.STATE_AUTO, + ], + climate.ATTR_MIN_TEMP: 10, + climate.ATTR_MAX_TEMP: 30, + ATTR_TEMPERATURE: 18, + climate.ATTR_CURRENT_TEMPERATURE: 20 + }), BASIC_CONFIG) + assert trt.sync_attributes() == { + 'availableThermostatModes': 'off,on,heatcool', + 'thermostatTemperatureUnit': 'C', + } + assert trt.query_attributes() == { + 'thermostatMode': 'heatcool', + 'thermostatTemperatureAmbient': 20, + 'thermostatTemperatureSetpointHigh': 18, + 'thermostatTemperatureSetpointLow': 18, + } + assert trt.can_execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, {}) + assert trt.can_execute(trait.COMMAND_THERMOSTAT_SET_MODE, {}) + + calls = async_mock_service( + hass, climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE) + + await trt.execute( + trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, BASIC_DATA, + {'thermostatTemperatureSetpoint': 19}) + assert len(calls) == 1 + assert calls[0].data == { + ATTR_ENTITY_ID: 'climate.bla', + ATTR_TEMPERATURE: 19 + } + + async def test_lock_unlock_lock(hass): """Test LockUnlock trait locking support for lock domain.""" assert trait.LockUnlockTrait.supported(lock.DOMAIN, lock.SUPPORT_OPEN)