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.
This commit is contained in:
Jerad Meisner 2018-08-22 00:17:29 -07:00 committed by Paulus Schoutsen
parent a31501d99e
commit ae63980152
14 changed files with 184 additions and 224 deletions

View file

@ -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())

View file

@ -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."""

View file

@ -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)

View file

@ -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):

View file

@ -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):

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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,

View file

@ -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

View file

@ -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."""

View file

@ -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

View file

@ -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

View file

@ -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