From ae6398015242ba0739cc17742899f825cf3f623b Mon Sep 17 00:00:00 2001 From: Jerad Meisner Date: Wed, 22 Aug 2018 00:17:29 -0700 Subject: [PATCH] Remove unit_of_measurement from climate entities (#16012) * Remove unit_of_measurement from climate base class. * Updated google_assistant component and tests to use core temp units. * Fixes * Convert Alexa component to use core temp units for climate entities. * Fix tests. * Converted prometheus component. * Remove unit_of_measurement from homekit thermostat tests. * Small fix. --- homeassistant/components/alexa/smart_home.py | 65 ++++----- homeassistant/components/climate/__init__.py | 7 +- .../components/climate/generic_thermostat.py | 10 +- homeassistant/components/climate/knx.py | 4 +- homeassistant/components/climate/maxcube.py | 3 +- homeassistant/components/climate/sensibo.py | 10 +- .../components/google_assistant/smart_home.py | 4 +- .../components/google_assistant/trait.py | 55 ++++---- homeassistant/components/prometheus.py | 13 +- tests/components/alexa/test_smart_home.py | 7 +- .../climate/test_generic_thermostat.py | 64 +++------ .../google_assistant/test_google_assistant.py | 3 +- .../components/google_assistant/test_trait.py | 123 +++++++++--------- .../homekit/test_type_thermostats.py | 40 ++---- 14 files changed, 184 insertions(+), 224 deletions(-) diff --git a/homeassistant/components/alexa/smart_home.py b/homeassistant/components/alexa/smart_home.py index 9fbcecfa577..eab725c4653 100644 --- a/homeassistant/components/alexa/smart_home.py +++ b/homeassistant/components/alexa/smart_home.py @@ -13,12 +13,13 @@ import homeassistant.util.color as color_util from homeassistant.util.temperature import convert as convert_temperature from homeassistant.util.decorator import Registry from homeassistant.const import ( - ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_TEMPERATURE, CONF_NAME, - SERVICE_LOCK, SERVICE_MEDIA_NEXT_TRACK, SERVICE_MEDIA_PAUSE, - SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PREVIOUS_TRACK, SERVICE_MEDIA_STOP, + ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_TEMPERATURE, + ATTR_UNIT_OF_MEASUREMENT, CONF_NAME, SERVICE_LOCK, + SERVICE_MEDIA_NEXT_TRACK, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, + SERVICE_MEDIA_PREVIOUS_TRACK, SERVICE_MEDIA_STOP, SERVICE_SET_COVER_POSITION, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_UNLOCK, SERVICE_VOLUME_SET, TEMP_FAHRENHEIT, TEMP_CELSIUS, - CONF_UNIT_OF_MEASUREMENT, STATE_LOCKED, STATE_UNLOCKED, STATE_ON) + STATE_LOCKED, STATE_UNLOCKED, STATE_ON) from .const import CONF_FILTER, CONF_ENTITY_CONFIG @@ -160,7 +161,8 @@ class _AlexaEntity: The API handlers should manipulate entities only through this interface. """ - def __init__(self, config, entity): + def __init__(self, hass, config, entity): + self.hass = hass self.config = config self.entity = entity self.entity_conf = config.entity_config.get(entity.entity_id, {}) @@ -384,6 +386,10 @@ class _AlexaInputController(_AlexaInterface): class _AlexaTemperatureSensor(_AlexaInterface): + def __init__(self, hass, entity): + _AlexaInterface.__init__(self, entity) + self.hass = hass + def name(self): return 'Alexa.TemperatureSensor' @@ -397,9 +403,10 @@ class _AlexaTemperatureSensor(_AlexaInterface): if name != 'temperature': raise _UnsupportedProperty(name) - unit = self.entity.attributes[CONF_UNIT_OF_MEASUREMENT] + unit = self.entity.attributes.get(ATTR_UNIT_OF_MEASUREMENT) temp = self.entity.state if self.entity.domain == climate.DOMAIN: + unit = self.hass.config.units.temperature_unit temp = self.entity.attributes.get( climate.ATTR_CURRENT_TEMPERATURE) return { @@ -409,6 +416,10 @@ class _AlexaTemperatureSensor(_AlexaInterface): class _AlexaThermostatController(_AlexaInterface): + def __init__(self, hass, entity): + _AlexaInterface.__init__(self, entity) + self.hass = hass + def name(self): return 'Alexa.ThermostatController' @@ -439,8 +450,7 @@ class _AlexaThermostatController(_AlexaInterface): raise _UnsupportedProperty(name) return mode - unit = self.entity.attributes[CONF_UNIT_OF_MEASUREMENT] - temp = None + unit = self.hass.config.units.temperature_unit if name == 'targetSetpoint': temp = self.entity.attributes.get(climate.ATTR_TEMPERATURE) elif name == 'lowerSetpoint': @@ -491,8 +501,8 @@ class _ClimateCapabilities(_AlexaEntity): return [_DisplayCategory.THERMOSTAT] def interfaces(self): - yield _AlexaThermostatController(self.entity) - yield _AlexaTemperatureSensor(self.entity) + yield _AlexaThermostatController(self.hass, self.entity) + yield _AlexaTemperatureSensor(self.hass, self.entity) @ENTITY_ADAPTERS.register(cover.DOMAIN) @@ -609,11 +619,11 @@ class _SensorCapabilities(_AlexaEntity): def interfaces(self): attrs = self.entity.attributes - if attrs.get(CONF_UNIT_OF_MEASUREMENT) in ( + if attrs.get(ATTR_UNIT_OF_MEASUREMENT) in ( TEMP_FAHRENHEIT, TEMP_CELSIUS, ): - yield _AlexaTemperatureSensor(self.entity) + yield _AlexaTemperatureSensor(self.hass, self.entity) class _Cause: @@ -823,7 +833,7 @@ async def async_api_discovery(hass, config, request, context): if entity.domain not in ENTITY_ADAPTERS: continue - alexa_entity = ENTITY_ADAPTERS[entity.domain](config, entity) + alexa_entity = ENTITY_ADAPTERS[entity.domain](hass, config, entity) endpoint = { 'displayCategories': alexa_entity.display_categories(), @@ -1364,11 +1374,12 @@ async def async_api_previous(hass, config, request, context, entity): return api_message(request) -def api_error_temp_range(request, temp, min_temp, max_temp, unit): +def api_error_temp_range(hass, request, temp, min_temp, max_temp): """Create temperature value out of range API error response. Async friendly. """ + unit = hass.config.units.temperature_unit temp_range = { 'minimumValue': { 'value': min_temp, @@ -1389,8 +1400,9 @@ def api_error_temp_range(request, temp, min_temp, max_temp, unit): ) -def temperature_from_object(temp_obj, to_unit, interval=False): +def temperature_from_object(hass, temp_obj, interval=False): """Get temperature from Temperature object in requested unit.""" + to_unit = hass.config.units.temperature_unit from_unit = TEMP_CELSIUS temp = float(temp_obj['value']) @@ -1408,7 +1420,6 @@ def temperature_from_object(temp_obj, to_unit, interval=False): @extract_entity async def async_api_set_target_temp(hass, config, request, context, entity): """Process a set target temperature request.""" - unit = entity.attributes[CONF_UNIT_OF_MEASUREMENT] min_temp = entity.attributes.get(climate.ATTR_MIN_TEMP) max_temp = entity.attributes.get(climate.ATTR_MAX_TEMP) @@ -1418,25 +1429,22 @@ async def async_api_set_target_temp(hass, config, request, context, entity): payload = request[API_PAYLOAD] if 'targetSetpoint' in payload: - temp = temperature_from_object( - payload['targetSetpoint'], unit) + temp = temperature_from_object(hass, payload['targetSetpoint']) if temp < min_temp or temp > max_temp: return api_error_temp_range( - request, temp, min_temp, max_temp, unit) + hass, request, temp, min_temp, max_temp) data[ATTR_TEMPERATURE] = temp if 'lowerSetpoint' in payload: - temp_low = temperature_from_object( - payload['lowerSetpoint'], unit) + temp_low = temperature_from_object(hass, payload['lowerSetpoint']) if temp_low < min_temp or temp_low > max_temp: return api_error_temp_range( - request, temp_low, min_temp, max_temp, unit) + hass, request, temp_low, min_temp, max_temp) data[climate.ATTR_TARGET_TEMP_LOW] = temp_low if 'upperSetpoint' in payload: - temp_high = temperature_from_object( - payload['upperSetpoint'], unit) + temp_high = temperature_from_object(hass, payload['upperSetpoint']) if temp_high < min_temp or temp_high > max_temp: return api_error_temp_range( - request, temp_high, min_temp, max_temp, unit) + hass, request, temp_high, min_temp, max_temp) data[climate.ATTR_TARGET_TEMP_HIGH] = temp_high await hass.services.async_call( @@ -1450,17 +1458,16 @@ async def async_api_set_target_temp(hass, config, request, context, entity): @extract_entity async def async_api_adjust_target_temp(hass, config, request, context, entity): """Process an adjust target temperature request.""" - unit = entity.attributes[CONF_UNIT_OF_MEASUREMENT] min_temp = entity.attributes.get(climate.ATTR_MIN_TEMP) max_temp = entity.attributes.get(climate.ATTR_MAX_TEMP) temp_delta = temperature_from_object( - request[API_PAYLOAD]['targetSetpointDelta'], unit, interval=True) + hass, request[API_PAYLOAD]['targetSetpointDelta'], interval=True) target_temp = float(entity.attributes.get(ATTR_TEMPERATURE)) + temp_delta if target_temp < min_temp or target_temp > max_temp: return api_error_temp_range( - request, target_temp, min_temp, max_temp, unit) + hass, request, target_temp, min_temp, max_temp) data = { ATTR_ENTITY_ID: entity.entity_id, @@ -1512,7 +1519,7 @@ async def async_api_set_thermostat_mode(hass, config, request, context, @extract_entity async def async_api_reportstate(hass, config, request, context, entity): """Process a ReportState request.""" - alexa_entity = ENTITY_ADAPTERS[entity.domain](config, entity) + alexa_entity = ENTITY_ADAPTERS[entity.domain](hass, config, entity) properties = [] for interface in alexa_entity.interfaces(): properties.extend(interface.serialize_properties()) diff --git a/homeassistant/components/climate/__init__.py b/homeassistant/components/climate/__init__.py index f33f68b9423..a3273f67cc2 100644 --- a/homeassistant/components/climate/__init__.py +++ b/homeassistant/components/climate/__init__.py @@ -320,7 +320,7 @@ class ClimateDevice(Entity): @property def precision(self): """Return the precision of the system.""" - if self.unit_of_measurement == TEMP_CELSIUS: + if self.hass.config.units.temperature_unit == TEMP_CELSIUS: return PRECISION_TENTHS return PRECISION_WHOLE @@ -394,11 +394,6 @@ class ClimateDevice(Entity): return data - @property - def unit_of_measurement(self): - """Return the unit of measurement to display.""" - return self.hass.config.units.temperature_unit - @property def temperature_unit(self): """Return the unit of measurement used by the platform.""" diff --git a/homeassistant/components/climate/generic_thermostat.py b/homeassistant/components/climate/generic_thermostat.py index 307c96bce32..9e5ff3bbf20 100644 --- a/homeassistant/components/climate/generic_thermostat.py +++ b/homeassistant/components/climate/generic_thermostat.py @@ -16,9 +16,8 @@ from homeassistant.components.climate import ( ATTR_OPERATION_MODE, ATTR_AWAY_MODE, SUPPORT_OPERATION_MODE, SUPPORT_AWAY_MODE, SUPPORT_TARGET_TEMPERATURE, PLATFORM_SCHEMA) from homeassistant.const import ( - ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF, ATTR_TEMPERATURE, - CONF_NAME, ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF, - STATE_UNKNOWN) + STATE_ON, STATE_OFF, ATTR_TEMPERATURE, CONF_NAME, ATTR_ENTITY_ID, + SERVICE_TURN_ON, SERVICE_TURN_OFF, STATE_UNKNOWN) from homeassistant.helpers import condition from homeassistant.helpers.event import ( async_track_state_change, async_track_time_interval) @@ -297,11 +296,8 @@ class GenericThermostat(ClimateDevice): @callback def _async_update_temp(self, state): """Update thermostat with latest state from sensor.""" - unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) - try: - self._cur_temp = self.hass.config.units.temperature( - float(state.state), unit) + self._cur_temp = float(state.state) except ValueError as ex: _LOGGER.error("Unable to update from sensor: %s", ex) diff --git a/homeassistant/components/climate/knx.py b/homeassistant/components/climate/knx.py index f53cf2491dc..1f95a8cb43d 100644 --- a/homeassistant/components/climate/knx.py +++ b/homeassistant/components/climate/knx.py @@ -122,8 +122,6 @@ class KNXClimate(ClimateDevice): self.hass = hass self.async_register_callbacks() - self._unit_of_measurement = TEMP_CELSIUS - @property def supported_features(self): """Return the list of supported features.""" @@ -157,7 +155,7 @@ class KNXClimate(ClimateDevice): @property def temperature_unit(self): """Return the unit of measurement.""" - return self._unit_of_measurement + return TEMP_CELSIUS @property def current_temperature(self): diff --git a/homeassistant/components/climate/maxcube.py b/homeassistant/components/climate/maxcube.py index 712ebb4f4ce..204d5a3649c 100644 --- a/homeassistant/components/climate/maxcube.py +++ b/homeassistant/components/climate/maxcube.py @@ -45,7 +45,6 @@ class MaxCubeClimate(ClimateDevice): def __init__(self, handler, name, rf_address): """Initialize MAX! Cube ClimateDevice.""" self._name = name - self._unit_of_measurement = TEMP_CELSIUS self._operation_list = [STATE_AUTO, STATE_MANUAL, STATE_BOOST, STATE_VACATION] self._rf_address = rf_address @@ -81,7 +80,7 @@ class MaxCubeClimate(ClimateDevice): @property def temperature_unit(self): """Return the unit of measurement.""" - return self._unit_of_measurement + return TEMP_CELSIUS @property def current_temperature(self): diff --git a/homeassistant/components/climate/sensibo.py b/homeassistant/components/climate/sensibo.py index 363653608e8..a2c4ea0ba99 100644 --- a/homeassistant/components/climate/sensibo.py +++ b/homeassistant/components/climate/sensibo.py @@ -71,7 +71,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): for dev in ( yield from client.async_get_devices(_INITIAL_FETCH_FIELDS)): if config[CONF_ID] == ALL or dev['id'] in config[CONF_ID]: - devices.append(SensiboClimate(client, dev)) + devices.append(SensiboClimate( + client, dev, hass.config.units.temperature_unit)) except (aiohttp.client_exceptions.ClientConnectorError, asyncio.TimeoutError): _LOGGER.exception('Failed to connect to Sensibo servers.') @@ -106,7 +107,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): class SensiboClimate(ClimateDevice): """Representation of a Sensibo device.""" - def __init__(self, client, data): + def __init__(self, client, data, units): """Build SensiboClimate. client: aiohttp session. @@ -115,6 +116,7 @@ class SensiboClimate(ClimateDevice): self._client = client self._id = data['id'] self._external_state = None + self._units = units self._do_update(data) @property @@ -139,7 +141,7 @@ class SensiboClimate(ClimateDevice): self._temperatures_list = self._current_capabilities[ 'temperatures'].get(temperature_unit_key, {}).get('values', []) else: - self._temperature_unit = self.unit_of_measurement + self._temperature_unit = self._units self._temperatures_list = [] self._supported_features = 0 for key in self._ac_states: @@ -175,7 +177,7 @@ class SensiboClimate(ClimateDevice): @property def target_temperature_step(self): """Return the supported step of target temperature.""" - if self.temperature_unit == self.unit_of_measurement: + if self.temperature_unit == self.hass.config.units.temperature_unit: # We are working in same units as the a/c unit. Use whole degrees # like the API supports. return 1 diff --git a/homeassistant/components/google_assistant/smart_home.py b/homeassistant/components/google_assistant/smart_home.py index 63a3e641170..675e86f9d39 100644 --- a/homeassistant/components/google_assistant/smart_home.py +++ b/homeassistant/components/google_assistant/smart_home.py @@ -77,7 +77,7 @@ class _GoogleEntity: domain = state.domain features = state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) - return [Trait(state) for Trait in trait.TRAITS + return [Trait(self.hass, state) for Trait in trait.TRAITS if Trait.supported(domain, features)] @callback @@ -159,7 +159,7 @@ class _GoogleEntity: executed = False for trt in self.traits(): if trt.can_execute(command, params): - await trt.execute(self.hass, command, params) + await trt.execute(command, params) executed = True break diff --git a/homeassistant/components/google_assistant/trait.py b/homeassistant/components/google_assistant/trait.py index 1d369eb87da..d45a84caaa3 100644 --- a/homeassistant/components/google_assistant/trait.py +++ b/homeassistant/components/google_assistant/trait.py @@ -14,7 +14,6 @@ from homeassistant.components import ( ) from homeassistant.const import ( ATTR_ENTITY_ID, - ATTR_UNIT_OF_MEASUREMENT, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_OFF, @@ -55,10 +54,9 @@ def register_trait(trait): return trait -def _google_temp_unit(state): +def _google_temp_unit(units): """Return Google temperature unit.""" - if (state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == - TEMP_FAHRENHEIT): + if units == TEMP_FAHRENHEIT: return 'F' return 'C' @@ -68,8 +66,9 @@ class _Trait: commands = [] - def __init__(self, state): + def __init__(self, hass, state): """Initialize a trait for a state.""" + self.hass = hass self.state = state def sync_attributes(self): @@ -84,7 +83,7 @@ class _Trait: """Test if command can be executed.""" return command in self.commands - async def execute(self, hass, command, params): + async def execute(self, command, params): """Execute a trait command.""" raise NotImplementedError @@ -141,24 +140,24 @@ class BrightnessTrait(_Trait): return response - async def execute(self, hass, command, params): + async def execute(self, command, params): """Execute a brightness command.""" domain = self.state.domain if domain == light.DOMAIN: - await hass.services.async_call( + await self.hass.services.async_call( light.DOMAIN, light.SERVICE_TURN_ON, { ATTR_ENTITY_ID: self.state.entity_id, light.ATTR_BRIGHTNESS_PCT: params['brightness'] }, blocking=True) elif domain == cover.DOMAIN: - await hass.services.async_call( + await self.hass.services.async_call( cover.DOMAIN, cover.SERVICE_SET_COVER_POSITION, { ATTR_ENTITY_ID: self.state.entity_id, cover.ATTR_POSITION: params['brightness'] }, blocking=True) elif domain == media_player.DOMAIN: - await hass.services.async_call( + await self.hass.services.async_call( media_player.DOMAIN, media_player.SERVICE_VOLUME_SET, { ATTR_ENTITY_ID: self.state.entity_id, media_player.ATTR_MEDIA_VOLUME_LEVEL: @@ -201,7 +200,7 @@ class OnOffTrait(_Trait): return {'on': self.state.state != cover.STATE_CLOSED} return {'on': self.state.state != STATE_OFF} - async def execute(self, hass, command, params): + async def execute(self, command, params): """Execute an OnOff command.""" domain = self.state.domain @@ -220,7 +219,7 @@ class OnOffTrait(_Trait): service_domain = domain service = SERVICE_TURN_ON if params['on'] else SERVICE_TURN_OFF - await hass.services.async_call(service_domain, service, { + await self.hass.services.async_call(service_domain, service, { ATTR_ENTITY_ID: self.state.entity_id }, blocking=True) @@ -268,14 +267,14 @@ class ColorSpectrumTrait(_Trait): return (command in self.commands and 'spectrumRGB' in params.get('color', {})) - async def execute(self, hass, command, params): + async def execute(self, command, params): """Execute a color spectrum command.""" # Convert integer to hex format and left pad with 0's till length 6 hex_value = "{0:06x}".format(params['color']['spectrumRGB']) color = color_util.color_RGB_to_hs( *color_util.rgb_hex_to_rgb_list(hex_value)) - await hass.services.async_call(light.DOMAIN, SERVICE_TURN_ON, { + await self.hass.services.async_call(light.DOMAIN, SERVICE_TURN_ON, { ATTR_ENTITY_ID: self.state.entity_id, light.ATTR_HS_COLOR: color }, blocking=True) @@ -331,7 +330,7 @@ class ColorTemperatureTrait(_Trait): return (command in self.commands and 'temperature' in params.get('color', {})) - async def execute(self, hass, command, params): + async def execute(self, command, params): """Execute a color temperature command.""" temp = color_util.color_temperature_kelvin_to_mired( params['color']['temperature']) @@ -344,7 +343,7 @@ class ColorTemperatureTrait(_Trait): "Temperature should be between {} and {}".format(min_temp, max_temp)) - await hass.services.async_call(light.DOMAIN, SERVICE_TURN_ON, { + await self.hass.services.async_call(light.DOMAIN, SERVICE_TURN_ON, { ATTR_ENTITY_ID: self.state.entity_id, light.ATTR_COLOR_TEMP: temp, }, blocking=True) @@ -376,12 +375,13 @@ class SceneTrait(_Trait): """Return scene query attributes.""" return {} - async def execute(self, hass, command, params): + async def execute(self, command, params): """Execute a scene command.""" # Don't block for scripts as they can be slow. - await hass.services.async_call(self.state.domain, SERVICE_TURN_ON, { - ATTR_ENTITY_ID: self.state.entity_id - }, blocking=self.state.domain != script.DOMAIN) + await self.hass.services.async_call( + self.state.domain, SERVICE_TURN_ON, { + ATTR_ENTITY_ID: self.state.entity_id + }, blocking=self.state.domain != script.DOMAIN) @register_trait @@ -425,7 +425,8 @@ class TemperatureSettingTrait(_Trait): return { 'availableThermostatModes': ','.join(modes), - 'thermostatTemperatureUnit': _google_temp_unit(self.state), + 'thermostatTemperatureUnit': _google_temp_unit( + self.hass.config.units.temperature_unit) } def query_attributes(self): @@ -437,7 +438,7 @@ class TemperatureSettingTrait(_Trait): if operation is not None and operation in self.hass_to_google: response['thermostatMode'] = self.hass_to_google[operation] - unit = self.state.attributes[ATTR_UNIT_OF_MEASUREMENT] + unit = self.hass.config.units.temperature_unit current_temp = attrs.get(climate.ATTR_CURRENT_TEMPERATURE) if current_temp is not None: @@ -465,10 +466,10 @@ class TemperatureSettingTrait(_Trait): return response - async def execute(self, hass, command, params): + async def execute(self, command, params): """Execute a temperature point or mode command.""" # All sent in temperatures are always in Celsius - unit = self.state.attributes[ATTR_UNIT_OF_MEASUREMENT] + unit = self.hass.config.units.temperature_unit min_temp = self.state.attributes[climate.ATTR_MIN_TEMP] max_temp = self.state.attributes[climate.ATTR_MAX_TEMP] @@ -482,7 +483,7 @@ class TemperatureSettingTrait(_Trait): "Temperature should be between {} and {}".format(min_temp, max_temp)) - await hass.services.async_call( + await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, { ATTR_ENTITY_ID: self.state.entity_id, climate.ATTR_TEMPERATURE: temp @@ -508,7 +509,7 @@ class TemperatureSettingTrait(_Trait): "Lower bound for temperature range should be between " "{} and {}".format(min_temp, max_temp)) - await hass.services.async_call( + 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, @@ -516,7 +517,7 @@ class TemperatureSettingTrait(_Trait): }, blocking=True) elif command == COMMAND_THERMOSTAT_SET_MODE: - await hass.services.async_call( + await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_OPERATION_MODE, { ATTR_ENTITY_ID: self.state.entity_id, climate.ATTR_OPERATION_MODE: diff --git a/homeassistant/components/prometheus.py b/homeassistant/components/prometheus.py index da986f024a4..5fa768b6983 100644 --- a/homeassistant/components/prometheus.py +++ b/homeassistant/components/prometheus.py @@ -49,7 +49,9 @@ def setup(hass, config): conf = config[DOMAIN] entity_filter = conf[CONF_FILTER] namespace = conf.get(CONF_PROM_NAMESPACE) - metrics = PrometheusMetrics(prometheus_client, entity_filter, namespace) + climate_units = hass.config.units.temperature_unit + metrics = PrometheusMetrics(prometheus_client, entity_filter, namespace, + climate_units) hass.bus.listen(EVENT_STATE_CHANGED, metrics.handle_event) return True @@ -58,7 +60,8 @@ def setup(hass, config): class PrometheusMetrics: """Model all of the metrics which should be exposed to Prometheus.""" - def __init__(self, prometheus_client, entity_filter, namespace): + def __init__(self, prometheus_client, entity_filter, namespace, + climate_units): """Initialize Prometheus Metrics.""" self.prometheus_client = prometheus_client self._filter = entity_filter @@ -67,6 +70,7 @@ class PrometheusMetrics: else: self.metrics_prefix = "" self._metrics = {} + self._climate_units = climate_units def handle_event(self, event): """Listen for new messages on the bus, and add them to Prometheus.""" @@ -173,8 +177,7 @@ class PrometheusMetrics: def _handle_climate(self, state): temp = state.attributes.get(ATTR_TEMPERATURE) if temp: - unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) - if unit == TEMP_FAHRENHEIT: + if self._climate_units == TEMP_FAHRENHEIT: temp = fahrenheit_to_celsius(temp) metric = self._metric( 'temperature_c', self.prometheus_client.Gauge, @@ -183,7 +186,7 @@ class PrometheusMetrics: current_temp = state.attributes.get(ATTR_CURRENT_TEMPERATURE) if current_temp: - if unit == TEMP_FAHRENHEIT: + if self._climate_units == TEMP_FAHRENHEIT: current_temp = fahrenheit_to_celsius(current_temp) metric = self._metric( 'current_temperature_c', self.prometheus_client.Gauge, diff --git a/tests/components/alexa/test_smart_home.py b/tests/components/alexa/test_smart_home.py index 1fc38b71c52..88c69194407 100644 --- a/tests/components/alexa/test_smart_home.py +++ b/tests/components/alexa/test_smart_home.py @@ -7,8 +7,8 @@ import pytest from homeassistant.core import Context, callback from homeassistant.const import ( - TEMP_FAHRENHEIT, STATE_LOCKED, STATE_UNLOCKED, - STATE_UNKNOWN) + TEMP_CELSIUS, TEMP_FAHRENHEIT, STATE_LOCKED, + STATE_UNLOCKED, STATE_UNKNOWN) from homeassistant.setup import async_setup_component from homeassistant.components import alexa from homeassistant.components.alexa import smart_home @@ -707,6 +707,7 @@ def test_unknown_sensor(hass): async def test_thermostat(hass): """Test thermostat discovery.""" + hass.config.units.temperature_unit = TEMP_FAHRENHEIT device = ( 'climate.test_thermostat', 'cool', @@ -721,7 +722,6 @@ async def test_thermostat(hass): 'operation_list': ['heat', 'cool', 'auto', 'off'], 'min_temp': 50, 'max_temp': 90, - 'unit_of_measurement': TEMP_FAHRENHEIT, } ) appliance = await discovery_test(device, hass) @@ -838,6 +838,7 @@ async def test_thermostat(hass): payload={'thermostatMode': {'value': 'INVALID'}} ) assert msg['event']['payload']['type'] == 'UNSUPPORTED_THERMOSTAT_MODE' + hass.config.units.temperature_unit = TEMP_CELSIUS @asyncio.coroutine diff --git a/tests/components/climate/test_generic_thermostat.py b/tests/components/climate/test_generic_thermostat.py index 59ddb004bec..ac587db13fa 100644 --- a/tests/components/climate/test_generic_thermostat.py +++ b/tests/components/climate/test_generic_thermostat.py @@ -9,7 +9,6 @@ import homeassistant.core as ha from homeassistant.core import callback, CoreState, State from homeassistant.setup import setup_component, async_setup_component from homeassistant.const import ( - ATTR_UNIT_OF_MEASUREMENT, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_ON, @@ -141,11 +140,9 @@ class TestGenericThermostatHeaterSwitching(unittest.TestCase): self.assertEqual(STATE_ON, self.hass.states.get(heater_switch).state) - def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + def _setup_sensor(self, temp): """Set up the test sensor.""" - self.hass.states.set(ENT_SENSOR, temp, { - ATTR_UNIT_OF_MEASUREMENT: unit - }) + self.hass.states.set(ENT_SENSOR, temp) class TestClimateGenericThermostat(unittest.TestCase): @@ -222,30 +219,15 @@ class TestClimateGenericThermostat(unittest.TestCase): state = self.hass.states.get(ENTITY) self.assertEqual(23, state.attributes.get('temperature')) - def test_sensor_bad_unit(self): - """Test sensor that have bad unit.""" - state = self.hass.states.get(ENTITY) - temp = state.attributes.get('current_temperature') - unit = state.attributes.get('unit_of_measurement') - - self._setup_sensor(22.0, unit='bad_unit') - self.hass.block_till_done() - - state = self.hass.states.get(ENTITY) - self.assertEqual(unit, state.attributes.get('unit_of_measurement')) - self.assertEqual(temp, state.attributes.get('current_temperature')) - def test_sensor_bad_value(self): """Test sensor that have None as state.""" state = self.hass.states.get(ENTITY) temp = state.attributes.get('current_temperature') - unit = state.attributes.get('unit_of_measurement') self._setup_sensor(None) self.hass.block_till_done() state = self.hass.states.get(ENTITY) - self.assertEqual(unit, state.attributes.get('unit_of_measurement')) self.assertEqual(temp, state.attributes.get('current_temperature')) def test_set_target_temp_heater_on(self): @@ -367,11 +349,9 @@ class TestClimateGenericThermostat(unittest.TestCase): self.assertEqual(SERVICE_TURN_ON, call.service) self.assertEqual(ENT_SWITCH, call.data['entity_id']) - def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + def _setup_sensor(self, temp): """Set up the test sensor.""" - self.hass.states.set(ENT_SENSOR, temp, { - ATTR_UNIT_OF_MEASUREMENT: unit - }) + self.hass.states.set(ENT_SENSOR, temp) def _setup_switch(self, is_on): """Set up the test switch.""" @@ -532,11 +512,9 @@ class TestClimateGenericThermostatACMode(unittest.TestCase): self.hass.block_till_done() self.assertEqual(0, len(self.calls)) - def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + def _setup_sensor(self, temp): """Set up the test sensor.""" - self.hass.states.set(ENT_SENSOR, temp, { - ATTR_UNIT_OF_MEASUREMENT: unit - }) + self.hass.states.set(ENT_SENSOR, temp) def _setup_switch(self, is_on): """Set up the test switch.""" @@ -626,11 +604,9 @@ class TestClimateGenericThermostatACModeMinCycle(unittest.TestCase): self.assertEqual(SERVICE_TURN_OFF, call.service) self.assertEqual(ENT_SWITCH, call.data['entity_id']) - def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + def _setup_sensor(self, temp): """Set up the test sensor.""" - self.hass.states.set(ENT_SENSOR, temp, { - ATTR_UNIT_OF_MEASUREMENT: unit - }) + self.hass.states.set(ENT_SENSOR, temp) def _setup_switch(self, is_on): """Set up the test switch.""" @@ -719,11 +695,9 @@ class TestClimateGenericThermostatMinCycle(unittest.TestCase): self.assertEqual(SERVICE_TURN_OFF, call.service) self.assertEqual(ENT_SWITCH, call.data['entity_id']) - def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + def _setup_sensor(self, temp): """Set up the test sensor.""" - self.hass.states.set(ENT_SENSOR, temp, { - ATTR_UNIT_OF_MEASUREMENT: unit - }) + self.hass.states.set(ENT_SENSOR, temp) def _setup_switch(self, is_on): """Set up the test switch.""" @@ -812,11 +786,9 @@ class TestClimateGenericThermostatACKeepAlive(unittest.TestCase): """Send a time changed event.""" self.hass.bus.fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: now}) - def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + def _setup_sensor(self, temp): """Set up the test sensor.""" - self.hass.states.set(ENT_SENSOR, temp, { - ATTR_UNIT_OF_MEASUREMENT: unit - }) + self.hass.states.set(ENT_SENSOR, temp) def _setup_switch(self, is_on): """Set up the test switch.""" @@ -904,11 +876,9 @@ class TestClimateGenericThermostatKeepAlive(unittest.TestCase): """Send a time changed event.""" self.hass.bus.fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: now}) - def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + def _setup_sensor(self, temp): """Set up the test sensor.""" - self.hass.states.set(ENT_SENSOR, temp, { - ATTR_UNIT_OF_MEASUREMENT: unit - }) + self.hass.states.set(ENT_SENSOR, temp) def _setup_switch(self, is_on): """Set up the test switch.""" @@ -1047,11 +1017,9 @@ class TestClimateGenericThermostatRestoreState(unittest.TestCase): 'ac_mode': True }}) - def _setup_sensor(self, temp, unit=TEMP_CELSIUS): + def _setup_sensor(self, temp): """Set up the test sensor.""" - self.hass.states.set(ENT_SENSOR, temp, { - ATTR_UNIT_OF_MEASUREMENT: unit - }) + self.hass.states.set(ENT_SENSOR, temp) def _setup_switch(self, is_on): """Set up the test switch.""" diff --git a/tests/components/google_assistant/test_google_assistant.py b/tests/components/google_assistant/test_google_assistant.py index d45680d132e..d9682940bdc 100644 --- a/tests/components/google_assistant/test_google_assistant.py +++ b/tests/components/google_assistant/test_google_assistant.py @@ -232,10 +232,10 @@ def test_query_climate_request(hass_fixture, assistant_client): def test_query_climate_request_f(hass_fixture, assistant_client): """Test a query request.""" # Mock demo devices as fahrenheit to see if we convert to celsius + hass_fixture.config.units.temperature_unit = const.TEMP_FAHRENHEIT for entity_id in ('climate.hvac', 'climate.heatpump', 'climate.ecobee'): state = hass_fixture.states.get(entity_id) attr = dict(state.attributes) - attr[const.ATTR_UNIT_OF_MEASUREMENT] = const.TEMP_FAHRENHEIT hass_fixture.states.async_set(entity_id, state.state, attr) reqid = '5711642932632160984' @@ -282,6 +282,7 @@ def test_query_climate_request_f(hass_fixture, assistant_client): 'thermostatMode': 'cool', 'thermostatHumidityAmbient': 54, } + hass_fixture.config.units.temperature_unit = const.TEMP_CELSIUS @asyncio.coroutine diff --git a/tests/components/google_assistant/test_trait.py b/tests/components/google_assistant/test_trait.py index 1f7ee011e61..c18ed4b7bf3 100644 --- a/tests/components/google_assistant/test_trait.py +++ b/tests/components/google_assistant/test_trait.py @@ -3,7 +3,7 @@ import pytest from homeassistant.const import ( STATE_ON, STATE_OFF, ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF, - ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS, TEMP_FAHRENHEIT) + TEMP_CELSIUS, TEMP_FAHRENHEIT) from homeassistant.core import State, DOMAIN as HA_DOMAIN from homeassistant.components import ( climate, @@ -27,7 +27,7 @@ async def test_brightness_light(hass): assert trait.BrightnessTrait.supported(light.DOMAIN, light.SUPPORT_BRIGHTNESS) - trt = trait.BrightnessTrait(State('light.bla', light.STATE_ON, { + trt = trait.BrightnessTrait(hass, State('light.bla', light.STATE_ON, { light.ATTR_BRIGHTNESS: 243 })) @@ -38,7 +38,7 @@ async def test_brightness_light(hass): } calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON) - await trt.execute(hass, trait.COMMAND_BRIGHTNESS_ABSOLUTE, { + await trt.execute(trait.COMMAND_BRIGHTNESS_ABSOLUTE, { 'brightness': 50 }) assert len(calls) == 1 @@ -53,7 +53,7 @@ async def test_brightness_cover(hass): assert trait.BrightnessTrait.supported(cover.DOMAIN, cover.SUPPORT_SET_POSITION) - trt = trait.BrightnessTrait(State('cover.bla', cover.STATE_OPEN, { + trt = trait.BrightnessTrait(hass, State('cover.bla', cover.STATE_OPEN, { cover.ATTR_CURRENT_POSITION: 75 })) @@ -65,7 +65,7 @@ async def test_brightness_cover(hass): calls = async_mock_service( hass, cover.DOMAIN, cover.SERVICE_SET_COVER_POSITION) - await trt.execute(hass, trait.COMMAND_BRIGHTNESS_ABSOLUTE, { + await trt.execute(trait.COMMAND_BRIGHTNESS_ABSOLUTE, { 'brightness': 50 }) assert len(calls) == 1 @@ -80,7 +80,7 @@ async def test_brightness_media_player(hass): assert trait.BrightnessTrait.supported(media_player.DOMAIN, media_player.SUPPORT_VOLUME_SET) - trt = trait.BrightnessTrait(State( + trt = trait.BrightnessTrait(hass, State( 'media_player.bla', media_player.STATE_PLAYING, { media_player.ATTR_MEDIA_VOLUME_LEVEL: .3 })) @@ -93,7 +93,7 @@ async def test_brightness_media_player(hass): calls = async_mock_service( hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_SET) - await trt.execute(hass, trait.COMMAND_BRIGHTNESS_ABSOLUTE, { + await trt.execute(trait.COMMAND_BRIGHTNESS_ABSOLUTE, { 'brightness': 60 }) assert len(calls) == 1 @@ -107,7 +107,7 @@ async def test_onoff_group(hass): """Test OnOff trait support for group domain.""" assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) - trt_on = trait.OnOffTrait(State('group.bla', STATE_ON)) + trt_on = trait.OnOffTrait(hass, State('group.bla', STATE_ON)) assert trt_on.sync_attributes() == {} @@ -115,13 +115,13 @@ async def test_onoff_group(hass): 'on': True } - trt_off = trait.OnOffTrait(State('group.bla', STATE_OFF)) + trt_off = trait.OnOffTrait(hass, State('group.bla', STATE_OFF)) assert trt_off.query_attributes() == { 'on': False } on_calls = async_mock_service(hass, HA_DOMAIN, SERVICE_TURN_ON) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': True }) assert len(on_calls) == 1 @@ -130,7 +130,7 @@ async def test_onoff_group(hass): } off_calls = async_mock_service(hass, HA_DOMAIN, SERVICE_TURN_OFF) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': False }) assert len(off_calls) == 1 @@ -143,7 +143,7 @@ async def test_onoff_input_boolean(hass): """Test OnOff trait support for input_boolean domain.""" assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) - trt_on = trait.OnOffTrait(State('input_boolean.bla', STATE_ON)) + trt_on = trait.OnOffTrait(hass, State('input_boolean.bla', STATE_ON)) assert trt_on.sync_attributes() == {} @@ -151,13 +151,13 @@ async def test_onoff_input_boolean(hass): 'on': True } - trt_off = trait.OnOffTrait(State('input_boolean.bla', STATE_OFF)) + trt_off = trait.OnOffTrait(hass, State('input_boolean.bla', STATE_OFF)) assert trt_off.query_attributes() == { 'on': False } on_calls = async_mock_service(hass, input_boolean.DOMAIN, SERVICE_TURN_ON) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': True }) assert len(on_calls) == 1 @@ -167,7 +167,7 @@ async def test_onoff_input_boolean(hass): off_calls = async_mock_service(hass, input_boolean.DOMAIN, SERVICE_TURN_OFF) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': False }) assert len(off_calls) == 1 @@ -180,7 +180,7 @@ async def test_onoff_switch(hass): """Test OnOff trait support for switch domain.""" assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) - trt_on = trait.OnOffTrait(State('switch.bla', STATE_ON)) + trt_on = trait.OnOffTrait(hass, State('switch.bla', STATE_ON)) assert trt_on.sync_attributes() == {} @@ -188,13 +188,13 @@ async def test_onoff_switch(hass): 'on': True } - trt_off = trait.OnOffTrait(State('switch.bla', STATE_OFF)) + trt_off = trait.OnOffTrait(hass, State('switch.bla', STATE_OFF)) assert trt_off.query_attributes() == { 'on': False } on_calls = async_mock_service(hass, switch.DOMAIN, SERVICE_TURN_ON) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': True }) assert len(on_calls) == 1 @@ -203,7 +203,7 @@ async def test_onoff_switch(hass): } off_calls = async_mock_service(hass, switch.DOMAIN, SERVICE_TURN_OFF) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': False }) assert len(off_calls) == 1 @@ -216,7 +216,7 @@ async def test_onoff_fan(hass): """Test OnOff trait support for fan domain.""" assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) - trt_on = trait.OnOffTrait(State('fan.bla', STATE_ON)) + trt_on = trait.OnOffTrait(hass, State('fan.bla', STATE_ON)) assert trt_on.sync_attributes() == {} @@ -224,13 +224,13 @@ async def test_onoff_fan(hass): 'on': True } - trt_off = trait.OnOffTrait(State('fan.bla', STATE_OFF)) + trt_off = trait.OnOffTrait(hass, State('fan.bla', STATE_OFF)) assert trt_off.query_attributes() == { 'on': False } on_calls = async_mock_service(hass, fan.DOMAIN, SERVICE_TURN_ON) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': True }) assert len(on_calls) == 1 @@ -239,7 +239,7 @@ async def test_onoff_fan(hass): } off_calls = async_mock_service(hass, fan.DOMAIN, SERVICE_TURN_OFF) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': False }) assert len(off_calls) == 1 @@ -252,7 +252,7 @@ async def test_onoff_light(hass): """Test OnOff trait support for light domain.""" assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) - trt_on = trait.OnOffTrait(State('light.bla', STATE_ON)) + trt_on = trait.OnOffTrait(hass, State('light.bla', STATE_ON)) assert trt_on.sync_attributes() == {} @@ -260,13 +260,13 @@ async def test_onoff_light(hass): 'on': True } - trt_off = trait.OnOffTrait(State('light.bla', STATE_OFF)) + trt_off = trait.OnOffTrait(hass, State('light.bla', STATE_OFF)) assert trt_off.query_attributes() == { 'on': False } on_calls = async_mock_service(hass, light.DOMAIN, SERVICE_TURN_ON) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': True }) assert len(on_calls) == 1 @@ -275,7 +275,7 @@ async def test_onoff_light(hass): } off_calls = async_mock_service(hass, light.DOMAIN, SERVICE_TURN_OFF) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': False }) assert len(off_calls) == 1 @@ -288,7 +288,7 @@ async def test_onoff_cover(hass): """Test OnOff trait support for cover domain.""" assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) - trt_on = trait.OnOffTrait(State('cover.bla', cover.STATE_OPEN)) + trt_on = trait.OnOffTrait(hass, State('cover.bla', cover.STATE_OPEN)) assert trt_on.sync_attributes() == {} @@ -296,13 +296,13 @@ async def test_onoff_cover(hass): 'on': True } - trt_off = trait.OnOffTrait(State('cover.bla', cover.STATE_CLOSED)) + trt_off = trait.OnOffTrait(hass, State('cover.bla', cover.STATE_CLOSED)) assert trt_off.query_attributes() == { 'on': False } on_calls = async_mock_service(hass, cover.DOMAIN, cover.SERVICE_OPEN_COVER) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': True }) assert len(on_calls) == 1 @@ -312,7 +312,7 @@ async def test_onoff_cover(hass): off_calls = async_mock_service(hass, cover.DOMAIN, cover.SERVICE_CLOSE_COVER) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': False }) assert len(off_calls) == 1 @@ -325,7 +325,7 @@ async def test_onoff_media_player(hass): """Test OnOff trait support for media_player domain.""" assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) - trt_on = trait.OnOffTrait(State('media_player.bla', STATE_ON)) + trt_on = trait.OnOffTrait(hass, State('media_player.bla', STATE_ON)) assert trt_on.sync_attributes() == {} @@ -333,13 +333,13 @@ async def test_onoff_media_player(hass): 'on': True } - trt_off = trait.OnOffTrait(State('media_player.bla', STATE_OFF)) + trt_off = trait.OnOffTrait(hass, State('media_player.bla', STATE_OFF)) assert trt_off.query_attributes() == { 'on': False } on_calls = async_mock_service(hass, media_player.DOMAIN, SERVICE_TURN_ON) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': True }) assert len(on_calls) == 1 @@ -348,7 +348,7 @@ async def test_onoff_media_player(hass): } off_calls = async_mock_service(hass, media_player.DOMAIN, SERVICE_TURN_OFF) - await trt_on.execute(hass, trait.COMMAND_ONOFF, { + await trt_on.execute(trait.COMMAND_ONOFF, { 'on': False }) assert len(off_calls) == 1 @@ -363,7 +363,7 @@ async def test_color_spectrum_light(hass): assert trait.ColorSpectrumTrait.supported(light.DOMAIN, light.SUPPORT_COLOR) - trt = trait.ColorSpectrumTrait(State('light.bla', STATE_ON, { + trt = trait.ColorSpectrumTrait(hass, State('light.bla', STATE_ON, { light.ATTR_HS_COLOR: (0, 94), })) @@ -389,7 +389,7 @@ async def test_color_spectrum_light(hass): }) calls = async_mock_service(hass, light.DOMAIN, SERVICE_TURN_ON) - await trt.execute(hass, trait.COMMAND_COLOR_ABSOLUTE, { + await trt.execute(trait.COMMAND_COLOR_ABSOLUTE, { 'color': { 'spectrumRGB': 1052927 } @@ -407,7 +407,7 @@ async def test_color_temperature_light(hass): assert trait.ColorTemperatureTrait.supported(light.DOMAIN, light.SUPPORT_COLOR_TEMP) - trt = trait.ColorTemperatureTrait(State('light.bla', STATE_ON, { + trt = trait.ColorTemperatureTrait(hass, State('light.bla', STATE_ON, { light.ATTR_MIN_MIREDS: 200, light.ATTR_COLOR_TEMP: 300, light.ATTR_MAX_MIREDS: 500, @@ -438,14 +438,14 @@ async def test_color_temperature_light(hass): calls = async_mock_service(hass, light.DOMAIN, SERVICE_TURN_ON) with pytest.raises(helpers.SmartHomeError) as err: - await trt.execute(hass, trait.COMMAND_COLOR_ABSOLUTE, { + await trt.execute(trait.COMMAND_COLOR_ABSOLUTE, { 'color': { 'temperature': 5555 } }) assert err.value.code == const.ERR_VALUE_OUT_OF_RANGE - await trt.execute(hass, trait.COMMAND_COLOR_ABSOLUTE, { + await trt.execute(trait.COMMAND_COLOR_ABSOLUTE, { 'color': { 'temperature': 2857 } @@ -461,13 +461,13 @@ async def test_scene_scene(hass): """Test Scene trait support for scene domain.""" assert trait.SceneTrait.supported(scene.DOMAIN, 0) - trt = trait.SceneTrait(State('scene.bla', scene.STATE)) + trt = trait.SceneTrait(hass, State('scene.bla', scene.STATE)) assert trt.sync_attributes() == {} assert trt.query_attributes() == {} assert trt.can_execute(trait.COMMAND_ACTIVATE_SCENE, {}) calls = async_mock_service(hass, scene.DOMAIN, SERVICE_TURN_ON) - await trt.execute(hass, trait.COMMAND_ACTIVATE_SCENE, {}) + await trt.execute(trait.COMMAND_ACTIVATE_SCENE, {}) assert len(calls) == 1 assert calls[0].data == { ATTR_ENTITY_ID: 'scene.bla', @@ -478,13 +478,13 @@ async def test_scene_script(hass): """Test Scene trait support for script domain.""" assert trait.SceneTrait.supported(script.DOMAIN, 0) - trt = trait.SceneTrait(State('script.bla', STATE_OFF)) + trt = trait.SceneTrait(hass, State('script.bla', STATE_OFF)) assert trt.sync_attributes() == {} assert trt.query_attributes() == {} assert trt.can_execute(trait.COMMAND_ACTIVATE_SCENE, {}) calls = async_mock_service(hass, script.DOMAIN, SERVICE_TURN_ON) - await trt.execute(hass, trait.COMMAND_ACTIVATE_SCENE, {}) + await trt.execute(trait.COMMAND_ACTIVATE_SCENE, {}) # We don't wait till script execution is done. await hass.async_block_till_done() @@ -501,7 +501,9 @@ async def test_temperature_setting_climate_range(hass): assert trait.TemperatureSettingTrait.supported( climate.DOMAIN, climate.SUPPORT_OPERATION_MODE) - trt = trait.TemperatureSettingTrait(State( + hass.config.units.temperature_unit = TEMP_FAHRENHEIT + + trt = trait.TemperatureSettingTrait(hass, State( 'climate.bla', climate.STATE_AUTO, { climate.ATTR_CURRENT_TEMPERATURE: 70, climate.ATTR_CURRENT_HUMIDITY: 25, @@ -515,8 +517,7 @@ async def test_temperature_setting_climate_range(hass): climate.ATTR_TARGET_TEMP_HIGH: 75, climate.ATTR_TARGET_TEMP_LOW: 65, climate.ATTR_MIN_TEMP: 50, - climate.ATTR_MAX_TEMP: 80, - ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT, + climate.ATTR_MAX_TEMP: 80 })) assert trt.sync_attributes() == { 'availableThermostatModes': 'off,cool,heat,heatcool', @@ -535,7 +536,7 @@ async def test_temperature_setting_climate_range(hass): calls = async_mock_service( hass, climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE) - await trt.execute(hass, trait.COMMAND_THERMOSTAT_TEMPERATURE_SET_RANGE, { + await trt.execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SET_RANGE, { 'thermostatTemperatureSetpointHigh': 25, 'thermostatTemperatureSetpointLow': 20, }) @@ -548,7 +549,7 @@ async def test_temperature_setting_climate_range(hass): calls = async_mock_service( hass, climate.DOMAIN, climate.SERVICE_SET_OPERATION_MODE) - await trt.execute(hass, trait.COMMAND_THERMOSTAT_SET_MODE, { + await trt.execute(trait.COMMAND_THERMOSTAT_SET_MODE, { 'thermostatMode': 'heatcool', }) assert len(calls) == 1 @@ -558,11 +559,11 @@ async def test_temperature_setting_climate_range(hass): } with pytest.raises(helpers.SmartHomeError) as err: - await trt.execute( - hass, trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, { - 'thermostatTemperatureSetpoint': -100, - }) + await trt.execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, { + 'thermostatTemperatureSetpoint': -100, + }) assert err.value.code == const.ERR_VALUE_OUT_OF_RANGE + hass.config.units.temperature_unit = TEMP_CELSIUS async def test_temperature_setting_climate_setpoint(hass): @@ -571,7 +572,9 @@ async def test_temperature_setting_climate_setpoint(hass): assert trait.TemperatureSettingTrait.supported( climate.DOMAIN, climate.SUPPORT_OPERATION_MODE) - trt = trait.TemperatureSettingTrait(State( + hass.config.units.temperature_unit = TEMP_CELSIUS + + trt = trait.TemperatureSettingTrait(hass, State( 'climate.bla', climate.STATE_AUTO, { climate.ATTR_OPERATION_MODE: climate.STATE_COOL, climate.ATTR_OPERATION_LIST: [ @@ -581,8 +584,7 @@ async def test_temperature_setting_climate_setpoint(hass): climate.ATTR_MIN_TEMP: 10, climate.ATTR_MAX_TEMP: 30, climate.ATTR_TEMPERATURE: 18, - climate.ATTR_CURRENT_TEMPERATURE: 20, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS, + climate.ATTR_CURRENT_TEMPERATURE: 20 })) assert trt.sync_attributes() == { 'availableThermostatModes': 'off,cool', @@ -601,12 +603,11 @@ async def test_temperature_setting_climate_setpoint(hass): hass, climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE) with pytest.raises(helpers.SmartHomeError): - await trt.execute( - hass, trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, { - 'thermostatTemperatureSetpoint': -100, - }) + await trt.execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, { + 'thermostatTemperatureSetpoint': -100, + }) - await trt.execute(hass, trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, { + await trt.execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, { 'thermostatTemperatureSetpoint': 19, }) assert len(calls) == 1 diff --git a/tests/components/homekit/test_type_thermostats.py b/tests/components/homekit/test_type_thermostats.py index 45c340e58c4..687a9e9513c 100644 --- a/tests/components/homekit/test_type_thermostats.py +++ b/tests/components/homekit/test_type_thermostats.py @@ -12,8 +12,8 @@ from homeassistant.components.climate import ( from homeassistant.components.homekit.const import ( PROP_MAX_VALUE, PROP_MIN_VALUE) from homeassistant.const import ( - ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, - CONF_TEMPERATURE_UNIT, STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT) + ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, CONF_TEMPERATURE_UNIT, STATE_OFF, + TEMP_FAHRENHEIT) from tests.common import async_mock_service from tests.components.homekit.common import patch_debounce @@ -58,8 +58,7 @@ async def test_default_thermostat(hass, hk_driver, cls): hass.states.async_set(entity_id, STATE_HEAT, {ATTR_OPERATION_MODE: STATE_HEAT, ATTR_TEMPERATURE: 22.0, - ATTR_CURRENT_TEMPERATURE: 18.0, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) + ATTR_CURRENT_TEMPERATURE: 18.0}) await hass.async_block_till_done() assert acc.char_target_temp.value == 22.0 assert acc.char_current_heat_cool.value == 1 @@ -70,8 +69,7 @@ async def test_default_thermostat(hass, hk_driver, cls): hass.states.async_set(entity_id, STATE_HEAT, {ATTR_OPERATION_MODE: STATE_HEAT, ATTR_TEMPERATURE: 22.0, - ATTR_CURRENT_TEMPERATURE: 23.0, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) + ATTR_CURRENT_TEMPERATURE: 23.0}) await hass.async_block_till_done() assert acc.char_target_temp.value == 22.0 assert acc.char_current_heat_cool.value == 0 @@ -82,8 +80,7 @@ async def test_default_thermostat(hass, hk_driver, cls): hass.states.async_set(entity_id, STATE_COOL, {ATTR_OPERATION_MODE: STATE_COOL, ATTR_TEMPERATURE: 20.0, - ATTR_CURRENT_TEMPERATURE: 25.0, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) + ATTR_CURRENT_TEMPERATURE: 25.0}) await hass.async_block_till_done() assert acc.char_target_temp.value == 20.0 assert acc.char_current_heat_cool.value == 2 @@ -94,8 +91,7 @@ async def test_default_thermostat(hass, hk_driver, cls): hass.states.async_set(entity_id, STATE_COOL, {ATTR_OPERATION_MODE: STATE_COOL, ATTR_TEMPERATURE: 20.0, - ATTR_CURRENT_TEMPERATURE: 19.0, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) + ATTR_CURRENT_TEMPERATURE: 19.0}) await hass.async_block_till_done() assert acc.char_target_temp.value == 20.0 assert acc.char_current_heat_cool.value == 0 @@ -106,8 +102,7 @@ async def test_default_thermostat(hass, hk_driver, cls): hass.states.async_set(entity_id, STATE_OFF, {ATTR_OPERATION_MODE: STATE_OFF, ATTR_TEMPERATURE: 22.0, - ATTR_CURRENT_TEMPERATURE: 18.0, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) + ATTR_CURRENT_TEMPERATURE: 18.0}) await hass.async_block_till_done() assert acc.char_target_temp.value == 22.0 assert acc.char_current_heat_cool.value == 0 @@ -119,8 +114,7 @@ async def test_default_thermostat(hass, hk_driver, cls): {ATTR_OPERATION_MODE: STATE_AUTO, ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL], ATTR_TEMPERATURE: 22.0, - ATTR_CURRENT_TEMPERATURE: 18.0, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) + ATTR_CURRENT_TEMPERATURE: 18.0}) await hass.async_block_till_done() assert acc.char_target_temp.value == 22.0 assert acc.char_current_heat_cool.value == 1 @@ -132,8 +126,7 @@ async def test_default_thermostat(hass, hk_driver, cls): {ATTR_OPERATION_MODE: STATE_AUTO, ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL], ATTR_TEMPERATURE: 22.0, - ATTR_CURRENT_TEMPERATURE: 25.0, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) + ATTR_CURRENT_TEMPERATURE: 25.0}) await hass.async_block_till_done() assert acc.char_target_temp.value == 22.0 assert acc.char_current_heat_cool.value == 2 @@ -145,8 +138,7 @@ async def test_default_thermostat(hass, hk_driver, cls): {ATTR_OPERATION_MODE: STATE_AUTO, ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL], ATTR_TEMPERATURE: 22.0, - ATTR_CURRENT_TEMPERATURE: 22.0, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) + ATTR_CURRENT_TEMPERATURE: 22.0}) await hass.async_block_till_done() assert acc.char_target_temp.value == 22.0 assert acc.char_current_heat_cool.value == 0 @@ -201,8 +193,7 @@ async def test_auto_thermostat(hass, hk_driver, cls): {ATTR_OPERATION_MODE: STATE_AUTO, ATTR_TARGET_TEMP_HIGH: 22.0, ATTR_TARGET_TEMP_LOW: 20.0, - ATTR_CURRENT_TEMPERATURE: 18.0, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) + ATTR_CURRENT_TEMPERATURE: 18.0}) await hass.async_block_till_done() assert acc.char_heating_thresh_temp.value == 20.0 assert acc.char_cooling_thresh_temp.value == 22.0 @@ -215,8 +206,7 @@ async def test_auto_thermostat(hass, hk_driver, cls): {ATTR_OPERATION_MODE: STATE_AUTO, ATTR_TARGET_TEMP_HIGH: 23.0, ATTR_TARGET_TEMP_LOW: 19.0, - ATTR_CURRENT_TEMPERATURE: 24.0, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) + ATTR_CURRENT_TEMPERATURE: 24.0}) await hass.async_block_till_done() assert acc.char_heating_thresh_temp.value == 19.0 assert acc.char_cooling_thresh_temp.value == 23.0 @@ -229,8 +219,7 @@ async def test_auto_thermostat(hass, hk_driver, cls): {ATTR_OPERATION_MODE: STATE_AUTO, ATTR_TARGET_TEMP_HIGH: 23.0, ATTR_TARGET_TEMP_LOW: 19.0, - ATTR_CURRENT_TEMPERATURE: 21.0, - ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) + ATTR_CURRENT_TEMPERATURE: 21.0}) await hass.async_block_till_done() assert acc.char_heating_thresh_temp.value == 19.0 assert acc.char_cooling_thresh_temp.value == 23.0 @@ -334,8 +323,7 @@ async def test_thermostat_fahrenheit(hass, hk_driver, cls): ATTR_TARGET_TEMP_HIGH: 75.2, ATTR_TARGET_TEMP_LOW: 68, ATTR_TEMPERATURE: 71.6, - ATTR_CURRENT_TEMPERATURE: 73.4, - ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT}) + ATTR_CURRENT_TEMPERATURE: 73.4}) await hass.async_block_till_done() assert acc.char_heating_thresh_temp.value == 20.0 assert acc.char_cooling_thresh_temp.value == 24.0