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.temperature import convert as convert_temperature
from homeassistant.util.decorator import Registry from homeassistant.util.decorator import Registry
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_TEMPERATURE, CONF_NAME, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_TEMPERATURE,
SERVICE_LOCK, SERVICE_MEDIA_NEXT_TRACK, SERVICE_MEDIA_PAUSE, ATTR_UNIT_OF_MEASUREMENT, CONF_NAME, SERVICE_LOCK,
SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PREVIOUS_TRACK, SERVICE_MEDIA_STOP, 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_SET_COVER_POSITION, SERVICE_TURN_OFF, SERVICE_TURN_ON,
SERVICE_UNLOCK, SERVICE_VOLUME_SET, TEMP_FAHRENHEIT, TEMP_CELSIUS, 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 from .const import CONF_FILTER, CONF_ENTITY_CONFIG
@ -160,7 +161,8 @@ class _AlexaEntity:
The API handlers should manipulate entities only through this interface. 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.config = config
self.entity = entity self.entity = entity
self.entity_conf = config.entity_config.get(entity.entity_id, {}) self.entity_conf = config.entity_config.get(entity.entity_id, {})
@ -384,6 +386,10 @@ class _AlexaInputController(_AlexaInterface):
class _AlexaTemperatureSensor(_AlexaInterface): class _AlexaTemperatureSensor(_AlexaInterface):
def __init__(self, hass, entity):
_AlexaInterface.__init__(self, entity)
self.hass = hass
def name(self): def name(self):
return 'Alexa.TemperatureSensor' return 'Alexa.TemperatureSensor'
@ -397,9 +403,10 @@ class _AlexaTemperatureSensor(_AlexaInterface):
if name != 'temperature': if name != 'temperature':
raise _UnsupportedProperty(name) raise _UnsupportedProperty(name)
unit = self.entity.attributes[CONF_UNIT_OF_MEASUREMENT] unit = self.entity.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
temp = self.entity.state temp = self.entity.state
if self.entity.domain == climate.DOMAIN: if self.entity.domain == climate.DOMAIN:
unit = self.hass.config.units.temperature_unit
temp = self.entity.attributes.get( temp = self.entity.attributes.get(
climate.ATTR_CURRENT_TEMPERATURE) climate.ATTR_CURRENT_TEMPERATURE)
return { return {
@ -409,6 +416,10 @@ class _AlexaTemperatureSensor(_AlexaInterface):
class _AlexaThermostatController(_AlexaInterface): class _AlexaThermostatController(_AlexaInterface):
def __init__(self, hass, entity):
_AlexaInterface.__init__(self, entity)
self.hass = hass
def name(self): def name(self):
return 'Alexa.ThermostatController' return 'Alexa.ThermostatController'
@ -439,8 +450,7 @@ class _AlexaThermostatController(_AlexaInterface):
raise _UnsupportedProperty(name) raise _UnsupportedProperty(name)
return mode return mode
unit = self.entity.attributes[CONF_UNIT_OF_MEASUREMENT] unit = self.hass.config.units.temperature_unit
temp = None
if name == 'targetSetpoint': if name == 'targetSetpoint':
temp = self.entity.attributes.get(climate.ATTR_TEMPERATURE) temp = self.entity.attributes.get(climate.ATTR_TEMPERATURE)
elif name == 'lowerSetpoint': elif name == 'lowerSetpoint':
@ -491,8 +501,8 @@ class _ClimateCapabilities(_AlexaEntity):
return [_DisplayCategory.THERMOSTAT] return [_DisplayCategory.THERMOSTAT]
def interfaces(self): def interfaces(self):
yield _AlexaThermostatController(self.entity) yield _AlexaThermostatController(self.hass, self.entity)
yield _AlexaTemperatureSensor(self.entity) yield _AlexaTemperatureSensor(self.hass, self.entity)
@ENTITY_ADAPTERS.register(cover.DOMAIN) @ENTITY_ADAPTERS.register(cover.DOMAIN)
@ -609,11 +619,11 @@ class _SensorCapabilities(_AlexaEntity):
def interfaces(self): def interfaces(self):
attrs = self.entity.attributes attrs = self.entity.attributes
if attrs.get(CONF_UNIT_OF_MEASUREMENT) in ( if attrs.get(ATTR_UNIT_OF_MEASUREMENT) in (
TEMP_FAHRENHEIT, TEMP_FAHRENHEIT,
TEMP_CELSIUS, TEMP_CELSIUS,
): ):
yield _AlexaTemperatureSensor(self.entity) yield _AlexaTemperatureSensor(self.hass, self.entity)
class _Cause: class _Cause:
@ -823,7 +833,7 @@ async def async_api_discovery(hass, config, request, context):
if entity.domain not in ENTITY_ADAPTERS: if entity.domain not in ENTITY_ADAPTERS:
continue continue
alexa_entity = ENTITY_ADAPTERS[entity.domain](config, entity) alexa_entity = ENTITY_ADAPTERS[entity.domain](hass, config, entity)
endpoint = { endpoint = {
'displayCategories': alexa_entity.display_categories(), 'displayCategories': alexa_entity.display_categories(),
@ -1364,11 +1374,12 @@ async def async_api_previous(hass, config, request, context, entity):
return api_message(request) 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. """Create temperature value out of range API error response.
Async friendly. Async friendly.
""" """
unit = hass.config.units.temperature_unit
temp_range = { temp_range = {
'minimumValue': { 'minimumValue': {
'value': min_temp, '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.""" """Get temperature from Temperature object in requested unit."""
to_unit = hass.config.units.temperature_unit
from_unit = TEMP_CELSIUS from_unit = TEMP_CELSIUS
temp = float(temp_obj['value']) temp = float(temp_obj['value'])
@ -1408,7 +1420,6 @@ def temperature_from_object(temp_obj, to_unit, interval=False):
@extract_entity @extract_entity
async def async_api_set_target_temp(hass, config, request, context, entity): async def async_api_set_target_temp(hass, config, request, context, entity):
"""Process a set target temperature request.""" """Process a set target temperature request."""
unit = entity.attributes[CONF_UNIT_OF_MEASUREMENT]
min_temp = entity.attributes.get(climate.ATTR_MIN_TEMP) min_temp = entity.attributes.get(climate.ATTR_MIN_TEMP)
max_temp = entity.attributes.get(climate.ATTR_MAX_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] payload = request[API_PAYLOAD]
if 'targetSetpoint' in payload: if 'targetSetpoint' in payload:
temp = temperature_from_object( temp = temperature_from_object(hass, payload['targetSetpoint'])
payload['targetSetpoint'], unit)
if temp < min_temp or temp > max_temp: if temp < min_temp or temp > max_temp:
return api_error_temp_range( return api_error_temp_range(
request, temp, min_temp, max_temp, unit) hass, request, temp, min_temp, max_temp)
data[ATTR_TEMPERATURE] = temp data[ATTR_TEMPERATURE] = temp
if 'lowerSetpoint' in payload: if 'lowerSetpoint' in payload:
temp_low = temperature_from_object( temp_low = temperature_from_object(hass, payload['lowerSetpoint'])
payload['lowerSetpoint'], unit)
if temp_low < min_temp or temp_low > max_temp: if temp_low < min_temp or temp_low > max_temp:
return api_error_temp_range( 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 data[climate.ATTR_TARGET_TEMP_LOW] = temp_low
if 'upperSetpoint' in payload: if 'upperSetpoint' in payload:
temp_high = temperature_from_object( temp_high = temperature_from_object(hass, payload['upperSetpoint'])
payload['upperSetpoint'], unit)
if temp_high < min_temp or temp_high > max_temp: if temp_high < min_temp or temp_high > max_temp:
return api_error_temp_range( 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 data[climate.ATTR_TARGET_TEMP_HIGH] = temp_high
await hass.services.async_call( await hass.services.async_call(
@ -1450,17 +1458,16 @@ async def async_api_set_target_temp(hass, config, request, context, entity):
@extract_entity @extract_entity
async def async_api_adjust_target_temp(hass, config, request, context, entity): async def async_api_adjust_target_temp(hass, config, request, context, entity):
"""Process an adjust target temperature request.""" """Process an adjust target temperature request."""
unit = entity.attributes[CONF_UNIT_OF_MEASUREMENT]
min_temp = entity.attributes.get(climate.ATTR_MIN_TEMP) min_temp = entity.attributes.get(climate.ATTR_MIN_TEMP)
max_temp = entity.attributes.get(climate.ATTR_MAX_TEMP) max_temp = entity.attributes.get(climate.ATTR_MAX_TEMP)
temp_delta = temperature_from_object( 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 target_temp = float(entity.attributes.get(ATTR_TEMPERATURE)) + temp_delta
if target_temp < min_temp or target_temp > max_temp: if target_temp < min_temp or target_temp > max_temp:
return api_error_temp_range( return api_error_temp_range(
request, target_temp, min_temp, max_temp, unit) hass, request, target_temp, min_temp, max_temp)
data = { data = {
ATTR_ENTITY_ID: entity.entity_id, ATTR_ENTITY_ID: entity.entity_id,
@ -1512,7 +1519,7 @@ async def async_api_set_thermostat_mode(hass, config, request, context,
@extract_entity @extract_entity
async def async_api_reportstate(hass, config, request, context, entity): async def async_api_reportstate(hass, config, request, context, entity):
"""Process a ReportState request.""" """Process a ReportState request."""
alexa_entity = ENTITY_ADAPTERS[entity.domain](config, entity) alexa_entity = ENTITY_ADAPTERS[entity.domain](hass, config, entity)
properties = [] properties = []
for interface in alexa_entity.interfaces(): for interface in alexa_entity.interfaces():
properties.extend(interface.serialize_properties()) properties.extend(interface.serialize_properties())

View File

@ -320,7 +320,7 @@ class ClimateDevice(Entity):
@property @property
def precision(self): def precision(self):
"""Return the precision of the system.""" """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_TENTHS
return PRECISION_WHOLE return PRECISION_WHOLE
@ -394,11 +394,6 @@ class ClimateDevice(Entity):
return data return data
@property
def unit_of_measurement(self):
"""Return the unit of measurement to display."""
return self.hass.config.units.temperature_unit
@property @property
def temperature_unit(self): def temperature_unit(self):
"""Return the unit of measurement used by the platform.""" """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, ATTR_OPERATION_MODE, ATTR_AWAY_MODE, SUPPORT_OPERATION_MODE,
SUPPORT_AWAY_MODE, SUPPORT_TARGET_TEMPERATURE, PLATFORM_SCHEMA) SUPPORT_AWAY_MODE, SUPPORT_TARGET_TEMPERATURE, PLATFORM_SCHEMA)
from homeassistant.const import ( from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, ATTR_TEMPERATURE, CONF_NAME, ATTR_ENTITY_ID,
CONF_NAME, ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_TURN_OFF, STATE_UNKNOWN)
STATE_UNKNOWN)
from homeassistant.helpers import condition from homeassistant.helpers import condition
from homeassistant.helpers.event import ( from homeassistant.helpers.event import (
async_track_state_change, async_track_time_interval) async_track_state_change, async_track_time_interval)
@ -297,11 +296,8 @@ class GenericThermostat(ClimateDevice):
@callback @callback
def _async_update_temp(self, state): def _async_update_temp(self, state):
"""Update thermostat with latest state from sensor.""" """Update thermostat with latest state from sensor."""
unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
try: try:
self._cur_temp = self.hass.config.units.temperature( self._cur_temp = float(state.state)
float(state.state), unit)
except ValueError as ex: except ValueError as ex:
_LOGGER.error("Unable to update from sensor: %s", ex) _LOGGER.error("Unable to update from sensor: %s", ex)

View File

@ -122,8 +122,6 @@ class KNXClimate(ClimateDevice):
self.hass = hass self.hass = hass
self.async_register_callbacks() self.async_register_callbacks()
self._unit_of_measurement = TEMP_CELSIUS
@property @property
def supported_features(self): def supported_features(self):
"""Return the list of supported features.""" """Return the list of supported features."""
@ -157,7 +155,7 @@ class KNXClimate(ClimateDevice):
@property @property
def temperature_unit(self): def temperature_unit(self):
"""Return the unit of measurement.""" """Return the unit of measurement."""
return self._unit_of_measurement return TEMP_CELSIUS
@property @property
def current_temperature(self): def current_temperature(self):

View File

@ -45,7 +45,6 @@ class MaxCubeClimate(ClimateDevice):
def __init__(self, handler, name, rf_address): def __init__(self, handler, name, rf_address):
"""Initialize MAX! Cube ClimateDevice.""" """Initialize MAX! Cube ClimateDevice."""
self._name = name self._name = name
self._unit_of_measurement = TEMP_CELSIUS
self._operation_list = [STATE_AUTO, STATE_MANUAL, STATE_BOOST, self._operation_list = [STATE_AUTO, STATE_MANUAL, STATE_BOOST,
STATE_VACATION] STATE_VACATION]
self._rf_address = rf_address self._rf_address = rf_address
@ -81,7 +80,7 @@ class MaxCubeClimate(ClimateDevice):
@property @property
def temperature_unit(self): def temperature_unit(self):
"""Return the unit of measurement.""" """Return the unit of measurement."""
return self._unit_of_measurement return TEMP_CELSIUS
@property @property
def current_temperature(self): 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 ( for dev in (
yield from client.async_get_devices(_INITIAL_FETCH_FIELDS)): yield from client.async_get_devices(_INITIAL_FETCH_FIELDS)):
if config[CONF_ID] == ALL or dev['id'] in config[CONF_ID]: 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, except (aiohttp.client_exceptions.ClientConnectorError,
asyncio.TimeoutError): asyncio.TimeoutError):
_LOGGER.exception('Failed to connect to Sensibo servers.') _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): class SensiboClimate(ClimateDevice):
"""Representation of a Sensibo device.""" """Representation of a Sensibo device."""
def __init__(self, client, data): def __init__(self, client, data, units):
"""Build SensiboClimate. """Build SensiboClimate.
client: aiohttp session. client: aiohttp session.
@ -115,6 +116,7 @@ class SensiboClimate(ClimateDevice):
self._client = client self._client = client
self._id = data['id'] self._id = data['id']
self._external_state = None self._external_state = None
self._units = units
self._do_update(data) self._do_update(data)
@property @property
@ -139,7 +141,7 @@ class SensiboClimate(ClimateDevice):
self._temperatures_list = self._current_capabilities[ self._temperatures_list = self._current_capabilities[
'temperatures'].get(temperature_unit_key, {}).get('values', []) 'temperatures'].get(temperature_unit_key, {}).get('values', [])
else: else:
self._temperature_unit = self.unit_of_measurement self._temperature_unit = self._units
self._temperatures_list = [] self._temperatures_list = []
self._supported_features = 0 self._supported_features = 0
for key in self._ac_states: for key in self._ac_states:
@ -175,7 +177,7 @@ class SensiboClimate(ClimateDevice):
@property @property
def target_temperature_step(self): def target_temperature_step(self):
"""Return the supported step of target temperature.""" """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 # We are working in same units as the a/c unit. Use whole degrees
# like the API supports. # like the API supports.
return 1 return 1

View File

@ -77,7 +77,7 @@ class _GoogleEntity:
domain = state.domain domain = state.domain
features = state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) 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)] if Trait.supported(domain, features)]
@callback @callback
@ -159,7 +159,7 @@ class _GoogleEntity:
executed = False executed = False
for trt in self.traits(): for trt in self.traits():
if trt.can_execute(command, params): if trt.can_execute(command, params):
await trt.execute(self.hass, command, params) await trt.execute(command, params)
executed = True executed = True
break break

View File

@ -14,7 +14,6 @@ from homeassistant.components import (
) )
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
ATTR_UNIT_OF_MEASUREMENT,
SERVICE_TURN_OFF, SERVICE_TURN_OFF,
SERVICE_TURN_ON, SERVICE_TURN_ON,
STATE_OFF, STATE_OFF,
@ -55,10 +54,9 @@ def register_trait(trait):
return trait return trait
def _google_temp_unit(state): def _google_temp_unit(units):
"""Return Google temperature unit.""" """Return Google temperature unit."""
if (state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == if units == TEMP_FAHRENHEIT:
TEMP_FAHRENHEIT):
return 'F' return 'F'
return 'C' return 'C'
@ -68,8 +66,9 @@ class _Trait:
commands = [] commands = []
def __init__(self, state): def __init__(self, hass, state):
"""Initialize a trait for a state.""" """Initialize a trait for a state."""
self.hass = hass
self.state = state self.state = state
def sync_attributes(self): def sync_attributes(self):
@ -84,7 +83,7 @@ class _Trait:
"""Test if command can be executed.""" """Test if command can be executed."""
return command in self.commands return command in self.commands
async def execute(self, hass, command, params): async def execute(self, command, params):
"""Execute a trait command.""" """Execute a trait command."""
raise NotImplementedError raise NotImplementedError
@ -141,24 +140,24 @@ class BrightnessTrait(_Trait):
return response return response
async def execute(self, hass, command, params): async def execute(self, command, params):
"""Execute a brightness command.""" """Execute a brightness command."""
domain = self.state.domain domain = self.state.domain
if domain == light.DOMAIN: if domain == light.DOMAIN:
await hass.services.async_call( await self.hass.services.async_call(
light.DOMAIN, light.SERVICE_TURN_ON, { light.DOMAIN, light.SERVICE_TURN_ON, {
ATTR_ENTITY_ID: self.state.entity_id, ATTR_ENTITY_ID: self.state.entity_id,
light.ATTR_BRIGHTNESS_PCT: params['brightness'] light.ATTR_BRIGHTNESS_PCT: params['brightness']
}, blocking=True) }, blocking=True)
elif domain == cover.DOMAIN: elif domain == cover.DOMAIN:
await hass.services.async_call( await self.hass.services.async_call(
cover.DOMAIN, cover.SERVICE_SET_COVER_POSITION, { cover.DOMAIN, cover.SERVICE_SET_COVER_POSITION, {
ATTR_ENTITY_ID: self.state.entity_id, ATTR_ENTITY_ID: self.state.entity_id,
cover.ATTR_POSITION: params['brightness'] cover.ATTR_POSITION: params['brightness']
}, blocking=True) }, blocking=True)
elif domain == media_player.DOMAIN: elif domain == media_player.DOMAIN:
await hass.services.async_call( await self.hass.services.async_call(
media_player.DOMAIN, media_player.SERVICE_VOLUME_SET, { media_player.DOMAIN, media_player.SERVICE_VOLUME_SET, {
ATTR_ENTITY_ID: self.state.entity_id, ATTR_ENTITY_ID: self.state.entity_id,
media_player.ATTR_MEDIA_VOLUME_LEVEL: 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 != cover.STATE_CLOSED}
return {'on': self.state.state != STATE_OFF} return {'on': self.state.state != STATE_OFF}
async def execute(self, hass, command, params): async def execute(self, command, params):
"""Execute an OnOff command.""" """Execute an OnOff command."""
domain = self.state.domain domain = self.state.domain
@ -220,7 +219,7 @@ class OnOffTrait(_Trait):
service_domain = domain service_domain = domain
service = SERVICE_TURN_ON if params['on'] else SERVICE_TURN_OFF 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 ATTR_ENTITY_ID: self.state.entity_id
}, blocking=True) }, blocking=True)
@ -268,14 +267,14 @@ class ColorSpectrumTrait(_Trait):
return (command in self.commands and return (command in self.commands and
'spectrumRGB' in params.get('color', {})) 'spectrumRGB' in params.get('color', {}))
async def execute(self, hass, command, params): async def execute(self, command, params):
"""Execute a color spectrum command.""" """Execute a color spectrum command."""
# Convert integer to hex format and left pad with 0's till length 6 # Convert integer to hex format and left pad with 0's till length 6
hex_value = "{0:06x}".format(params['color']['spectrumRGB']) hex_value = "{0:06x}".format(params['color']['spectrumRGB'])
color = color_util.color_RGB_to_hs( color = color_util.color_RGB_to_hs(
*color_util.rgb_hex_to_rgb_list(hex_value)) *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, ATTR_ENTITY_ID: self.state.entity_id,
light.ATTR_HS_COLOR: color light.ATTR_HS_COLOR: color
}, blocking=True) }, blocking=True)
@ -331,7 +330,7 @@ class ColorTemperatureTrait(_Trait):
return (command in self.commands and return (command in self.commands and
'temperature' in params.get('color', {})) 'temperature' in params.get('color', {}))
async def execute(self, hass, command, params): async def execute(self, command, params):
"""Execute a color temperature command.""" """Execute a color temperature command."""
temp = color_util.color_temperature_kelvin_to_mired( temp = color_util.color_temperature_kelvin_to_mired(
params['color']['temperature']) params['color']['temperature'])
@ -344,7 +343,7 @@ class ColorTemperatureTrait(_Trait):
"Temperature should be between {} and {}".format(min_temp, "Temperature should be between {} and {}".format(min_temp,
max_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, ATTR_ENTITY_ID: self.state.entity_id,
light.ATTR_COLOR_TEMP: temp, light.ATTR_COLOR_TEMP: temp,
}, blocking=True) }, blocking=True)
@ -376,10 +375,11 @@ class SceneTrait(_Trait):
"""Return scene query attributes.""" """Return scene query attributes."""
return {} return {}
async def execute(self, hass, command, params): async def execute(self, command, params):
"""Execute a scene command.""" """Execute a scene command."""
# Don't block for scripts as they can be slow. # Don't block for scripts as they can be slow.
await hass.services.async_call(self.state.domain, SERVICE_TURN_ON, { await self.hass.services.async_call(
self.state.domain, SERVICE_TURN_ON, {
ATTR_ENTITY_ID: self.state.entity_id ATTR_ENTITY_ID: self.state.entity_id
}, blocking=self.state.domain != script.DOMAIN) }, blocking=self.state.domain != script.DOMAIN)
@ -425,7 +425,8 @@ class TemperatureSettingTrait(_Trait):
return { return {
'availableThermostatModes': ','.join(modes), 'availableThermostatModes': ','.join(modes),
'thermostatTemperatureUnit': _google_temp_unit(self.state), 'thermostatTemperatureUnit': _google_temp_unit(
self.hass.config.units.temperature_unit)
} }
def query_attributes(self): def query_attributes(self):
@ -437,7 +438,7 @@ class TemperatureSettingTrait(_Trait):
if operation is not None and operation in self.hass_to_google: if operation is not None and operation in self.hass_to_google:
response['thermostatMode'] = self.hass_to_google[operation] 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) current_temp = attrs.get(climate.ATTR_CURRENT_TEMPERATURE)
if current_temp is not None: if current_temp is not None:
@ -465,10 +466,10 @@ class TemperatureSettingTrait(_Trait):
return response return response
async def execute(self, hass, command, params): async def execute(self, command, params):
"""Execute a temperature point or mode command.""" """Execute a temperature point or mode command."""
# All sent in temperatures are always in Celsius # 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] min_temp = self.state.attributes[climate.ATTR_MIN_TEMP]
max_temp = self.state.attributes[climate.ATTR_MAX_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, "Temperature should be between {} and {}".format(min_temp,
max_temp)) max_temp))
await hass.services.async_call( await self.hass.services.async_call(
climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, { climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, {
ATTR_ENTITY_ID: self.state.entity_id, ATTR_ENTITY_ID: self.state.entity_id,
climate.ATTR_TEMPERATURE: temp climate.ATTR_TEMPERATURE: temp
@ -508,7 +509,7 @@ class TemperatureSettingTrait(_Trait):
"Lower bound for temperature range should be between " "Lower bound for temperature range should be between "
"{} and {}".format(min_temp, max_temp)) "{} and {}".format(min_temp, max_temp))
await hass.services.async_call( await self.hass.services.async_call(
climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, { climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, {
ATTR_ENTITY_ID: self.state.entity_id, ATTR_ENTITY_ID: self.state.entity_id,
climate.ATTR_TARGET_TEMP_HIGH: temp_high, climate.ATTR_TARGET_TEMP_HIGH: temp_high,
@ -516,7 +517,7 @@ class TemperatureSettingTrait(_Trait):
}, blocking=True) }, blocking=True)
elif command == COMMAND_THERMOSTAT_SET_MODE: elif command == COMMAND_THERMOSTAT_SET_MODE:
await hass.services.async_call( await self.hass.services.async_call(
climate.DOMAIN, climate.SERVICE_SET_OPERATION_MODE, { climate.DOMAIN, climate.SERVICE_SET_OPERATION_MODE, {
ATTR_ENTITY_ID: self.state.entity_id, ATTR_ENTITY_ID: self.state.entity_id,
climate.ATTR_OPERATION_MODE: climate.ATTR_OPERATION_MODE:

View File

@ -49,7 +49,9 @@ def setup(hass, config):
conf = config[DOMAIN] conf = config[DOMAIN]
entity_filter = conf[CONF_FILTER] entity_filter = conf[CONF_FILTER]
namespace = conf.get(CONF_PROM_NAMESPACE) 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) hass.bus.listen(EVENT_STATE_CHANGED, metrics.handle_event)
return True return True
@ -58,7 +60,8 @@ def setup(hass, config):
class PrometheusMetrics: class PrometheusMetrics:
"""Model all of the metrics which should be exposed to Prometheus.""" """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.""" """Initialize Prometheus Metrics."""
self.prometheus_client = prometheus_client self.prometheus_client = prometheus_client
self._filter = entity_filter self._filter = entity_filter
@ -67,6 +70,7 @@ class PrometheusMetrics:
else: else:
self.metrics_prefix = "" self.metrics_prefix = ""
self._metrics = {} self._metrics = {}
self._climate_units = climate_units
def handle_event(self, event): def handle_event(self, event):
"""Listen for new messages on the bus, and add them to Prometheus.""" """Listen for new messages on the bus, and add them to Prometheus."""
@ -173,8 +177,7 @@ class PrometheusMetrics:
def _handle_climate(self, state): def _handle_climate(self, state):
temp = state.attributes.get(ATTR_TEMPERATURE) temp = state.attributes.get(ATTR_TEMPERATURE)
if temp: if temp:
unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) if self._climate_units == TEMP_FAHRENHEIT:
if unit == TEMP_FAHRENHEIT:
temp = fahrenheit_to_celsius(temp) temp = fahrenheit_to_celsius(temp)
metric = self._metric( metric = self._metric(
'temperature_c', self.prometheus_client.Gauge, 'temperature_c', self.prometheus_client.Gauge,
@ -183,7 +186,7 @@ class PrometheusMetrics:
current_temp = state.attributes.get(ATTR_CURRENT_TEMPERATURE) current_temp = state.attributes.get(ATTR_CURRENT_TEMPERATURE)
if current_temp: if current_temp:
if unit == TEMP_FAHRENHEIT: if self._climate_units == TEMP_FAHRENHEIT:
current_temp = fahrenheit_to_celsius(current_temp) current_temp = fahrenheit_to_celsius(current_temp)
metric = self._metric( metric = self._metric(
'current_temperature_c', self.prometheus_client.Gauge, 'current_temperature_c', self.prometheus_client.Gauge,

View File

@ -7,8 +7,8 @@ import pytest
from homeassistant.core import Context, callback from homeassistant.core import Context, callback
from homeassistant.const import ( from homeassistant.const import (
TEMP_FAHRENHEIT, STATE_LOCKED, STATE_UNLOCKED, TEMP_CELSIUS, TEMP_FAHRENHEIT, STATE_LOCKED,
STATE_UNKNOWN) STATE_UNLOCKED, STATE_UNKNOWN)
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
from homeassistant.components import alexa from homeassistant.components import alexa
from homeassistant.components.alexa import smart_home from homeassistant.components.alexa import smart_home
@ -707,6 +707,7 @@ def test_unknown_sensor(hass):
async def test_thermostat(hass): async def test_thermostat(hass):
"""Test thermostat discovery.""" """Test thermostat discovery."""
hass.config.units.temperature_unit = TEMP_FAHRENHEIT
device = ( device = (
'climate.test_thermostat', 'climate.test_thermostat',
'cool', 'cool',
@ -721,7 +722,6 @@ async def test_thermostat(hass):
'operation_list': ['heat', 'cool', 'auto', 'off'], 'operation_list': ['heat', 'cool', 'auto', 'off'],
'min_temp': 50, 'min_temp': 50,
'max_temp': 90, 'max_temp': 90,
'unit_of_measurement': TEMP_FAHRENHEIT,
} }
) )
appliance = await discovery_test(device, hass) appliance = await discovery_test(device, hass)
@ -838,6 +838,7 @@ async def test_thermostat(hass):
payload={'thermostatMode': {'value': 'INVALID'}} payload={'thermostatMode': {'value': 'INVALID'}}
) )
assert msg['event']['payload']['type'] == 'UNSUPPORTED_THERMOSTAT_MODE' assert msg['event']['payload']['type'] == 'UNSUPPORTED_THERMOSTAT_MODE'
hass.config.units.temperature_unit = TEMP_CELSIUS
@asyncio.coroutine @asyncio.coroutine

View File

@ -9,7 +9,6 @@ import homeassistant.core as ha
from homeassistant.core import callback, CoreState, State from homeassistant.core import callback, CoreState, State
from homeassistant.setup import setup_component, async_setup_component from homeassistant.setup import setup_component, async_setup_component
from homeassistant.const import ( from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT,
SERVICE_TURN_OFF, SERVICE_TURN_OFF,
SERVICE_TURN_ON, SERVICE_TURN_ON,
STATE_ON, STATE_ON,
@ -141,11 +140,9 @@ class TestGenericThermostatHeaterSwitching(unittest.TestCase):
self.assertEqual(STATE_ON, self.assertEqual(STATE_ON,
self.hass.states.get(heater_switch).state) 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.""" """Set up the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, { self.hass.states.set(ENT_SENSOR, temp)
ATTR_UNIT_OF_MEASUREMENT: unit
})
class TestClimateGenericThermostat(unittest.TestCase): class TestClimateGenericThermostat(unittest.TestCase):
@ -222,30 +219,15 @@ class TestClimateGenericThermostat(unittest.TestCase):
state = self.hass.states.get(ENTITY) state = self.hass.states.get(ENTITY)
self.assertEqual(23, state.attributes.get('temperature')) 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): def test_sensor_bad_value(self):
"""Test sensor that have None as state.""" """Test sensor that have None as state."""
state = self.hass.states.get(ENTITY) state = self.hass.states.get(ENTITY)
temp = state.attributes.get('current_temperature') temp = state.attributes.get('current_temperature')
unit = state.attributes.get('unit_of_measurement')
self._setup_sensor(None) self._setup_sensor(None)
self.hass.block_till_done() self.hass.block_till_done()
state = self.hass.states.get(ENTITY) state = self.hass.states.get(ENTITY)
self.assertEqual(unit, state.attributes.get('unit_of_measurement'))
self.assertEqual(temp, state.attributes.get('current_temperature')) self.assertEqual(temp, state.attributes.get('current_temperature'))
def test_set_target_temp_heater_on(self): 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(SERVICE_TURN_ON, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id']) 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.""" """Set up the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, { self.hass.states.set(ENT_SENSOR, temp)
ATTR_UNIT_OF_MEASUREMENT: unit
})
def _setup_switch(self, is_on): def _setup_switch(self, is_on):
"""Set up the test switch.""" """Set up the test switch."""
@ -532,11 +512,9 @@ class TestClimateGenericThermostatACMode(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
self.assertEqual(0, len(self.calls)) self.assertEqual(0, len(self.calls))
def _setup_sensor(self, temp, unit=TEMP_CELSIUS): def _setup_sensor(self, temp):
"""Set up the test sensor.""" """Set up the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, { self.hass.states.set(ENT_SENSOR, temp)
ATTR_UNIT_OF_MEASUREMENT: unit
})
def _setup_switch(self, is_on): def _setup_switch(self, is_on):
"""Set up the test switch.""" """Set up the test switch."""
@ -626,11 +604,9 @@ class TestClimateGenericThermostatACModeMinCycle(unittest.TestCase):
self.assertEqual(SERVICE_TURN_OFF, call.service) self.assertEqual(SERVICE_TURN_OFF, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id']) 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.""" """Set up the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, { self.hass.states.set(ENT_SENSOR, temp)
ATTR_UNIT_OF_MEASUREMENT: unit
})
def _setup_switch(self, is_on): def _setup_switch(self, is_on):
"""Set up the test switch.""" """Set up the test switch."""
@ -719,11 +695,9 @@ class TestClimateGenericThermostatMinCycle(unittest.TestCase):
self.assertEqual(SERVICE_TURN_OFF, call.service) self.assertEqual(SERVICE_TURN_OFF, call.service)
self.assertEqual(ENT_SWITCH, call.data['entity_id']) 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.""" """Set up the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, { self.hass.states.set(ENT_SENSOR, temp)
ATTR_UNIT_OF_MEASUREMENT: unit
})
def _setup_switch(self, is_on): def _setup_switch(self, is_on):
"""Set up the test switch.""" """Set up the test switch."""
@ -812,11 +786,9 @@ class TestClimateGenericThermostatACKeepAlive(unittest.TestCase):
"""Send a time changed event.""" """Send a time changed event."""
self.hass.bus.fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: now}) 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.""" """Set up the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, { self.hass.states.set(ENT_SENSOR, temp)
ATTR_UNIT_OF_MEASUREMENT: unit
})
def _setup_switch(self, is_on): def _setup_switch(self, is_on):
"""Set up the test switch.""" """Set up the test switch."""
@ -904,11 +876,9 @@ class TestClimateGenericThermostatKeepAlive(unittest.TestCase):
"""Send a time changed event.""" """Send a time changed event."""
self.hass.bus.fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: now}) 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.""" """Set up the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, { self.hass.states.set(ENT_SENSOR, temp)
ATTR_UNIT_OF_MEASUREMENT: unit
})
def _setup_switch(self, is_on): def _setup_switch(self, is_on):
"""Set up the test switch.""" """Set up the test switch."""
@ -1047,11 +1017,9 @@ class TestClimateGenericThermostatRestoreState(unittest.TestCase):
'ac_mode': True 'ac_mode': True
}}) }})
def _setup_sensor(self, temp, unit=TEMP_CELSIUS): def _setup_sensor(self, temp):
"""Set up the test sensor.""" """Set up the test sensor."""
self.hass.states.set(ENT_SENSOR, temp, { self.hass.states.set(ENT_SENSOR, temp)
ATTR_UNIT_OF_MEASUREMENT: unit
})
def _setup_switch(self, is_on): def _setup_switch(self, is_on):
"""Set up the test switch.""" """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): def test_query_climate_request_f(hass_fixture, assistant_client):
"""Test a query request.""" """Test a query request."""
# Mock demo devices as fahrenheit to see if we convert to celsius # 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'): for entity_id in ('climate.hvac', 'climate.heatpump', 'climate.ecobee'):
state = hass_fixture.states.get(entity_id) state = hass_fixture.states.get(entity_id)
attr = dict(state.attributes) attr = dict(state.attributes)
attr[const.ATTR_UNIT_OF_MEASUREMENT] = const.TEMP_FAHRENHEIT
hass_fixture.states.async_set(entity_id, state.state, attr) hass_fixture.states.async_set(entity_id, state.state, attr)
reqid = '5711642932632160984' reqid = '5711642932632160984'
@ -282,6 +282,7 @@ def test_query_climate_request_f(hass_fixture, assistant_client):
'thermostatMode': 'cool', 'thermostatMode': 'cool',
'thermostatHumidityAmbient': 54, 'thermostatHumidityAmbient': 54,
} }
hass_fixture.config.units.temperature_unit = const.TEMP_CELSIUS
@asyncio.coroutine @asyncio.coroutine

View File

@ -3,7 +3,7 @@ import pytest
from homeassistant.const import ( from homeassistant.const import (
STATE_ON, STATE_OFF, ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF, 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.core import State, DOMAIN as HA_DOMAIN
from homeassistant.components import ( from homeassistant.components import (
climate, climate,
@ -27,7 +27,7 @@ async def test_brightness_light(hass):
assert trait.BrightnessTrait.supported(light.DOMAIN, assert trait.BrightnessTrait.supported(light.DOMAIN,
light.SUPPORT_BRIGHTNESS) 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 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) 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 'brightness': 50
}) })
assert len(calls) == 1 assert len(calls) == 1
@ -53,7 +53,7 @@ async def test_brightness_cover(hass):
assert trait.BrightnessTrait.supported(cover.DOMAIN, assert trait.BrightnessTrait.supported(cover.DOMAIN,
cover.SUPPORT_SET_POSITION) 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 cover.ATTR_CURRENT_POSITION: 75
})) }))
@ -65,7 +65,7 @@ async def test_brightness_cover(hass):
calls = async_mock_service( calls = async_mock_service(
hass, cover.DOMAIN, cover.SERVICE_SET_COVER_POSITION) 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 'brightness': 50
}) })
assert len(calls) == 1 assert len(calls) == 1
@ -80,7 +80,7 @@ async def test_brightness_media_player(hass):
assert trait.BrightnessTrait.supported(media_player.DOMAIN, assert trait.BrightnessTrait.supported(media_player.DOMAIN,
media_player.SUPPORT_VOLUME_SET) media_player.SUPPORT_VOLUME_SET)
trt = trait.BrightnessTrait(State( trt = trait.BrightnessTrait(hass, State(
'media_player.bla', media_player.STATE_PLAYING, { 'media_player.bla', media_player.STATE_PLAYING, {
media_player.ATTR_MEDIA_VOLUME_LEVEL: .3 media_player.ATTR_MEDIA_VOLUME_LEVEL: .3
})) }))
@ -93,7 +93,7 @@ async def test_brightness_media_player(hass):
calls = async_mock_service( calls = async_mock_service(
hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_SET) 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 'brightness': 60
}) })
assert len(calls) == 1 assert len(calls) == 1
@ -107,7 +107,7 @@ async def test_onoff_group(hass):
"""Test OnOff trait support for group domain.""" """Test OnOff trait support for group domain."""
assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) 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() == {} assert trt_on.sync_attributes() == {}
@ -115,13 +115,13 @@ async def test_onoff_group(hass):
'on': True '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() == { assert trt_off.query_attributes() == {
'on': False 'on': False
} }
on_calls = async_mock_service(hass, HA_DOMAIN, SERVICE_TURN_ON) 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 'on': True
}) })
assert len(on_calls) == 1 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) 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 'on': False
}) })
assert len(off_calls) == 1 assert len(off_calls) == 1
@ -143,7 +143,7 @@ async def test_onoff_input_boolean(hass):
"""Test OnOff trait support for input_boolean domain.""" """Test OnOff trait support for input_boolean domain."""
assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) 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() == {} assert trt_on.sync_attributes() == {}
@ -151,13 +151,13 @@ async def test_onoff_input_boolean(hass):
'on': True '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() == { assert trt_off.query_attributes() == {
'on': False 'on': False
} }
on_calls = async_mock_service(hass, input_boolean.DOMAIN, SERVICE_TURN_ON) 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 'on': True
}) })
assert len(on_calls) == 1 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, off_calls = async_mock_service(hass, input_boolean.DOMAIN,
SERVICE_TURN_OFF) SERVICE_TURN_OFF)
await trt_on.execute(hass, trait.COMMAND_ONOFF, { await trt_on.execute(trait.COMMAND_ONOFF, {
'on': False 'on': False
}) })
assert len(off_calls) == 1 assert len(off_calls) == 1
@ -180,7 +180,7 @@ async def test_onoff_switch(hass):
"""Test OnOff trait support for switch domain.""" """Test OnOff trait support for switch domain."""
assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) 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() == {} assert trt_on.sync_attributes() == {}
@ -188,13 +188,13 @@ async def test_onoff_switch(hass):
'on': True '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() == { assert trt_off.query_attributes() == {
'on': False 'on': False
} }
on_calls = async_mock_service(hass, switch.DOMAIN, SERVICE_TURN_ON) 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 'on': True
}) })
assert len(on_calls) == 1 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) 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 'on': False
}) })
assert len(off_calls) == 1 assert len(off_calls) == 1
@ -216,7 +216,7 @@ async def test_onoff_fan(hass):
"""Test OnOff trait support for fan domain.""" """Test OnOff trait support for fan domain."""
assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) 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() == {} assert trt_on.sync_attributes() == {}
@ -224,13 +224,13 @@ async def test_onoff_fan(hass):
'on': True '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() == { assert trt_off.query_attributes() == {
'on': False 'on': False
} }
on_calls = async_mock_service(hass, fan.DOMAIN, SERVICE_TURN_ON) 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 'on': True
}) })
assert len(on_calls) == 1 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) 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 'on': False
}) })
assert len(off_calls) == 1 assert len(off_calls) == 1
@ -252,7 +252,7 @@ async def test_onoff_light(hass):
"""Test OnOff trait support for light domain.""" """Test OnOff trait support for light domain."""
assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) 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() == {} assert trt_on.sync_attributes() == {}
@ -260,13 +260,13 @@ async def test_onoff_light(hass):
'on': True '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() == { assert trt_off.query_attributes() == {
'on': False 'on': False
} }
on_calls = async_mock_service(hass, light.DOMAIN, SERVICE_TURN_ON) 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 'on': True
}) })
assert len(on_calls) == 1 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) 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 'on': False
}) })
assert len(off_calls) == 1 assert len(off_calls) == 1
@ -288,7 +288,7 @@ async def test_onoff_cover(hass):
"""Test OnOff trait support for cover domain.""" """Test OnOff trait support for cover domain."""
assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) 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() == {} assert trt_on.sync_attributes() == {}
@ -296,13 +296,13 @@ async def test_onoff_cover(hass):
'on': True '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() == { assert trt_off.query_attributes() == {
'on': False 'on': False
} }
on_calls = async_mock_service(hass, cover.DOMAIN, cover.SERVICE_OPEN_COVER) 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 'on': True
}) })
assert len(on_calls) == 1 assert len(on_calls) == 1
@ -312,7 +312,7 @@ async def test_onoff_cover(hass):
off_calls = async_mock_service(hass, cover.DOMAIN, off_calls = async_mock_service(hass, cover.DOMAIN,
cover.SERVICE_CLOSE_COVER) cover.SERVICE_CLOSE_COVER)
await trt_on.execute(hass, trait.COMMAND_ONOFF, { await trt_on.execute(trait.COMMAND_ONOFF, {
'on': False 'on': False
}) })
assert len(off_calls) == 1 assert len(off_calls) == 1
@ -325,7 +325,7 @@ async def test_onoff_media_player(hass):
"""Test OnOff trait support for media_player domain.""" """Test OnOff trait support for media_player domain."""
assert trait.OnOffTrait.supported(media_player.DOMAIN, 0) 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() == {} assert trt_on.sync_attributes() == {}
@ -333,13 +333,13 @@ async def test_onoff_media_player(hass):
'on': True '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() == { assert trt_off.query_attributes() == {
'on': False 'on': False
} }
on_calls = async_mock_service(hass, media_player.DOMAIN, SERVICE_TURN_ON) 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 'on': True
}) })
assert len(on_calls) == 1 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) 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 'on': False
}) })
assert len(off_calls) == 1 assert len(off_calls) == 1
@ -363,7 +363,7 @@ async def test_color_spectrum_light(hass):
assert trait.ColorSpectrumTrait.supported(light.DOMAIN, assert trait.ColorSpectrumTrait.supported(light.DOMAIN,
light.SUPPORT_COLOR) 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), 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) 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': { 'color': {
'spectrumRGB': 1052927 'spectrumRGB': 1052927
} }
@ -407,7 +407,7 @@ async def test_color_temperature_light(hass):
assert trait.ColorTemperatureTrait.supported(light.DOMAIN, assert trait.ColorTemperatureTrait.supported(light.DOMAIN,
light.SUPPORT_COLOR_TEMP) 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_MIN_MIREDS: 200,
light.ATTR_COLOR_TEMP: 300, light.ATTR_COLOR_TEMP: 300,
light.ATTR_MAX_MIREDS: 500, 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) calls = async_mock_service(hass, light.DOMAIN, SERVICE_TURN_ON)
with pytest.raises(helpers.SmartHomeError) as err: with pytest.raises(helpers.SmartHomeError) as err:
await trt.execute(hass, trait.COMMAND_COLOR_ABSOLUTE, { await trt.execute(trait.COMMAND_COLOR_ABSOLUTE, {
'color': { 'color': {
'temperature': 5555 'temperature': 5555
} }
}) })
assert err.value.code == const.ERR_VALUE_OUT_OF_RANGE 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': { 'color': {
'temperature': 2857 'temperature': 2857
} }
@ -461,13 +461,13 @@ async def test_scene_scene(hass):
"""Test Scene trait support for scene domain.""" """Test Scene trait support for scene domain."""
assert trait.SceneTrait.supported(scene.DOMAIN, 0) 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.sync_attributes() == {}
assert trt.query_attributes() == {} assert trt.query_attributes() == {}
assert trt.can_execute(trait.COMMAND_ACTIVATE_SCENE, {}) assert trt.can_execute(trait.COMMAND_ACTIVATE_SCENE, {})
calls = async_mock_service(hass, scene.DOMAIN, SERVICE_TURN_ON) 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 len(calls) == 1
assert calls[0].data == { assert calls[0].data == {
ATTR_ENTITY_ID: 'scene.bla', ATTR_ENTITY_ID: 'scene.bla',
@ -478,13 +478,13 @@ async def test_scene_script(hass):
"""Test Scene trait support for script domain.""" """Test Scene trait support for script domain."""
assert trait.SceneTrait.supported(script.DOMAIN, 0) 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.sync_attributes() == {}
assert trt.query_attributes() == {} assert trt.query_attributes() == {}
assert trt.can_execute(trait.COMMAND_ACTIVATE_SCENE, {}) assert trt.can_execute(trait.COMMAND_ACTIVATE_SCENE, {})
calls = async_mock_service(hass, script.DOMAIN, SERVICE_TURN_ON) 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. # We don't wait till script execution is done.
await hass.async_block_till_done() await hass.async_block_till_done()
@ -501,7 +501,9 @@ async def test_temperature_setting_climate_range(hass):
assert trait.TemperatureSettingTrait.supported( assert trait.TemperatureSettingTrait.supported(
climate.DOMAIN, climate.SUPPORT_OPERATION_MODE) 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.bla', climate.STATE_AUTO, {
climate.ATTR_CURRENT_TEMPERATURE: 70, climate.ATTR_CURRENT_TEMPERATURE: 70,
climate.ATTR_CURRENT_HUMIDITY: 25, 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_HIGH: 75,
climate.ATTR_TARGET_TEMP_LOW: 65, climate.ATTR_TARGET_TEMP_LOW: 65,
climate.ATTR_MIN_TEMP: 50, climate.ATTR_MIN_TEMP: 50,
climate.ATTR_MAX_TEMP: 80, climate.ATTR_MAX_TEMP: 80
ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT,
})) }))
assert trt.sync_attributes() == { assert trt.sync_attributes() == {
'availableThermostatModes': 'off,cool,heat,heatcool', 'availableThermostatModes': 'off,cool,heat,heatcool',
@ -535,7 +536,7 @@ async def test_temperature_setting_climate_range(hass):
calls = async_mock_service( calls = async_mock_service(
hass, climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE) 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, 'thermostatTemperatureSetpointHigh': 25,
'thermostatTemperatureSetpointLow': 20, 'thermostatTemperatureSetpointLow': 20,
}) })
@ -548,7 +549,7 @@ async def test_temperature_setting_climate_range(hass):
calls = async_mock_service( calls = async_mock_service(
hass, climate.DOMAIN, climate.SERVICE_SET_OPERATION_MODE) 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', 'thermostatMode': 'heatcool',
}) })
assert len(calls) == 1 assert len(calls) == 1
@ -558,11 +559,11 @@ async def test_temperature_setting_climate_range(hass):
} }
with pytest.raises(helpers.SmartHomeError) as err: with pytest.raises(helpers.SmartHomeError) as err:
await trt.execute( await trt.execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, {
hass, trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, {
'thermostatTemperatureSetpoint': -100, 'thermostatTemperatureSetpoint': -100,
}) })
assert err.value.code == const.ERR_VALUE_OUT_OF_RANGE 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): async def test_temperature_setting_climate_setpoint(hass):
@ -571,7 +572,9 @@ async def test_temperature_setting_climate_setpoint(hass):
assert trait.TemperatureSettingTrait.supported( assert trait.TemperatureSettingTrait.supported(
climate.DOMAIN, climate.SUPPORT_OPERATION_MODE) 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.bla', climate.STATE_AUTO, {
climate.ATTR_OPERATION_MODE: climate.STATE_COOL, climate.ATTR_OPERATION_MODE: climate.STATE_COOL,
climate.ATTR_OPERATION_LIST: [ climate.ATTR_OPERATION_LIST: [
@ -581,8 +584,7 @@ async def test_temperature_setting_climate_setpoint(hass):
climate.ATTR_MIN_TEMP: 10, climate.ATTR_MIN_TEMP: 10,
climate.ATTR_MAX_TEMP: 30, climate.ATTR_MAX_TEMP: 30,
climate.ATTR_TEMPERATURE: 18, climate.ATTR_TEMPERATURE: 18,
climate.ATTR_CURRENT_TEMPERATURE: 20, climate.ATTR_CURRENT_TEMPERATURE: 20
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
})) }))
assert trt.sync_attributes() == { assert trt.sync_attributes() == {
'availableThermostatModes': 'off,cool', 'availableThermostatModes': 'off,cool',
@ -601,12 +603,11 @@ async def test_temperature_setting_climate_setpoint(hass):
hass, climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE) hass, climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE)
with pytest.raises(helpers.SmartHomeError): with pytest.raises(helpers.SmartHomeError):
await trt.execute( await trt.execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, {
hass, trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, {
'thermostatTemperatureSetpoint': -100, 'thermostatTemperatureSetpoint': -100,
}) })
await trt.execute(hass, trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, { await trt.execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, {
'thermostatTemperatureSetpoint': 19, 'thermostatTemperatureSetpoint': 19,
}) })
assert len(calls) == 1 assert len(calls) == 1

View File

@ -12,8 +12,8 @@ from homeassistant.components.climate import (
from homeassistant.components.homekit.const import ( from homeassistant.components.homekit.const import (
PROP_MAX_VALUE, PROP_MIN_VALUE) PROP_MAX_VALUE, PROP_MIN_VALUE)
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, CONF_TEMPERATURE_UNIT, STATE_OFF,
CONF_TEMPERATURE_UNIT, STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT) TEMP_FAHRENHEIT)
from tests.common import async_mock_service from tests.common import async_mock_service
from tests.components.homekit.common import patch_debounce 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, hass.states.async_set(entity_id, STATE_HEAT,
{ATTR_OPERATION_MODE: STATE_HEAT, {ATTR_OPERATION_MODE: STATE_HEAT,
ATTR_TEMPERATURE: 22.0, ATTR_TEMPERATURE: 22.0,
ATTR_CURRENT_TEMPERATURE: 18.0, ATTR_CURRENT_TEMPERATURE: 18.0})
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_target_temp.value == 22.0 assert acc.char_target_temp.value == 22.0
assert acc.char_current_heat_cool.value == 1 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, hass.states.async_set(entity_id, STATE_HEAT,
{ATTR_OPERATION_MODE: STATE_HEAT, {ATTR_OPERATION_MODE: STATE_HEAT,
ATTR_TEMPERATURE: 22.0, ATTR_TEMPERATURE: 22.0,
ATTR_CURRENT_TEMPERATURE: 23.0, ATTR_CURRENT_TEMPERATURE: 23.0})
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_target_temp.value == 22.0 assert acc.char_target_temp.value == 22.0
assert acc.char_current_heat_cool.value == 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, hass.states.async_set(entity_id, STATE_COOL,
{ATTR_OPERATION_MODE: STATE_COOL, {ATTR_OPERATION_MODE: STATE_COOL,
ATTR_TEMPERATURE: 20.0, ATTR_TEMPERATURE: 20.0,
ATTR_CURRENT_TEMPERATURE: 25.0, ATTR_CURRENT_TEMPERATURE: 25.0})
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_target_temp.value == 20.0 assert acc.char_target_temp.value == 20.0
assert acc.char_current_heat_cool.value == 2 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, hass.states.async_set(entity_id, STATE_COOL,
{ATTR_OPERATION_MODE: STATE_COOL, {ATTR_OPERATION_MODE: STATE_COOL,
ATTR_TEMPERATURE: 20.0, ATTR_TEMPERATURE: 20.0,
ATTR_CURRENT_TEMPERATURE: 19.0, ATTR_CURRENT_TEMPERATURE: 19.0})
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_target_temp.value == 20.0 assert acc.char_target_temp.value == 20.0
assert acc.char_current_heat_cool.value == 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, hass.states.async_set(entity_id, STATE_OFF,
{ATTR_OPERATION_MODE: STATE_OFF, {ATTR_OPERATION_MODE: STATE_OFF,
ATTR_TEMPERATURE: 22.0, ATTR_TEMPERATURE: 22.0,
ATTR_CURRENT_TEMPERATURE: 18.0, ATTR_CURRENT_TEMPERATURE: 18.0})
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_target_temp.value == 22.0 assert acc.char_target_temp.value == 22.0
assert acc.char_current_heat_cool.value == 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_MODE: STATE_AUTO,
ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL], ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL],
ATTR_TEMPERATURE: 22.0, ATTR_TEMPERATURE: 22.0,
ATTR_CURRENT_TEMPERATURE: 18.0, ATTR_CURRENT_TEMPERATURE: 18.0})
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_target_temp.value == 22.0 assert acc.char_target_temp.value == 22.0
assert acc.char_current_heat_cool.value == 1 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_MODE: STATE_AUTO,
ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL], ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL],
ATTR_TEMPERATURE: 22.0, ATTR_TEMPERATURE: 22.0,
ATTR_CURRENT_TEMPERATURE: 25.0, ATTR_CURRENT_TEMPERATURE: 25.0})
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_target_temp.value == 22.0 assert acc.char_target_temp.value == 22.0
assert acc.char_current_heat_cool.value == 2 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_MODE: STATE_AUTO,
ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL], ATTR_OPERATION_LIST: [STATE_HEAT, STATE_COOL],
ATTR_TEMPERATURE: 22.0, ATTR_TEMPERATURE: 22.0,
ATTR_CURRENT_TEMPERATURE: 22.0, ATTR_CURRENT_TEMPERATURE: 22.0})
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_target_temp.value == 22.0 assert acc.char_target_temp.value == 22.0
assert acc.char_current_heat_cool.value == 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_OPERATION_MODE: STATE_AUTO,
ATTR_TARGET_TEMP_HIGH: 22.0, ATTR_TARGET_TEMP_HIGH: 22.0,
ATTR_TARGET_TEMP_LOW: 20.0, ATTR_TARGET_TEMP_LOW: 20.0,
ATTR_CURRENT_TEMPERATURE: 18.0, ATTR_CURRENT_TEMPERATURE: 18.0})
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_heating_thresh_temp.value == 20.0 assert acc.char_heating_thresh_temp.value == 20.0
assert acc.char_cooling_thresh_temp.value == 22.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_OPERATION_MODE: STATE_AUTO,
ATTR_TARGET_TEMP_HIGH: 23.0, ATTR_TARGET_TEMP_HIGH: 23.0,
ATTR_TARGET_TEMP_LOW: 19.0, ATTR_TARGET_TEMP_LOW: 19.0,
ATTR_CURRENT_TEMPERATURE: 24.0, ATTR_CURRENT_TEMPERATURE: 24.0})
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_heating_thresh_temp.value == 19.0 assert acc.char_heating_thresh_temp.value == 19.0
assert acc.char_cooling_thresh_temp.value == 23.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_OPERATION_MODE: STATE_AUTO,
ATTR_TARGET_TEMP_HIGH: 23.0, ATTR_TARGET_TEMP_HIGH: 23.0,
ATTR_TARGET_TEMP_LOW: 19.0, ATTR_TARGET_TEMP_LOW: 19.0,
ATTR_CURRENT_TEMPERATURE: 21.0, ATTR_CURRENT_TEMPERATURE: 21.0})
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_heating_thresh_temp.value == 19.0 assert acc.char_heating_thresh_temp.value == 19.0
assert acc.char_cooling_thresh_temp.value == 23.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_HIGH: 75.2,
ATTR_TARGET_TEMP_LOW: 68, ATTR_TARGET_TEMP_LOW: 68,
ATTR_TEMPERATURE: 71.6, ATTR_TEMPERATURE: 71.6,
ATTR_CURRENT_TEMPERATURE: 73.4, ATTR_CURRENT_TEMPERATURE: 73.4})
ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT})
await hass.async_block_till_done() await hass.async_block_till_done()
assert acc.char_heating_thresh_temp.value == 20.0 assert acc.char_heating_thresh_temp.value == 20.0
assert acc.char_cooling_thresh_temp.value == 24.0 assert acc.char_cooling_thresh_temp.value == 24.0