Allow emulated hue to set climate component temperature (#19034)

pull/21922/head
Thiago Oliveira 2019-03-10 16:04:21 -07:00 committed by Anders Melchiorsen
parent 5debc8828a
commit 77dc7595ee
3 changed files with 135 additions and 9 deletions

View File

@ -1,4 +1,4 @@
"""Proides the constants needed for component."""
"""Provides the constants needed for component."""
ATTR_AUX_HEAT = 'aux_heat'
ATTR_AWAY_MODE = 'away_mode'

View File

@ -5,13 +5,16 @@ from aiohttp import web
from homeassistant import core
from homeassistant.const import (
ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_SET,
SERVICE_OPEN_COVER, SERVICE_CLOSE_COVER, STATE_ON, STATE_OFF,
HTTP_BAD_REQUEST, HTTP_NOT_FOUND, ATTR_SUPPORTED_FEATURES,
ATTR_ENTITY_ID, ATTR_TEMPERATURE, SERVICE_TURN_OFF, SERVICE_TURN_ON,
SERVICE_VOLUME_SET, SERVICE_OPEN_COVER, SERVICE_CLOSE_COVER, STATE_ON,
STATE_OFF, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, ATTR_SUPPORTED_FEATURES
)
from homeassistant.components.light import (
ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS
)
from homeassistant.components.climate.const import (
SERVICE_SET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE
)
from homeassistant.components.media_player.const import (
ATTR_MEDIA_VOLUME_LEVEL, SUPPORT_VOLUME_SET,
)
@ -26,7 +29,7 @@ from homeassistant.components.cover import (
)
from homeassistant.components import (
cover, fan, media_player, light, script, scene
climate, cover, fan, media_player, light, script, scene
)
from homeassistant.components.http import HomeAssistantView
@ -262,6 +265,18 @@ class HueOneLightChangeView(HomeAssistantView):
if brightness is not None:
data['variables']['requested_level'] = brightness
# If the requested entity is a climate, set the temperature
elif entity.domain == climate.DOMAIN:
# We don't support turning climate devices on or off,
# only setting the temperature
service = None
if entity_features & SUPPORT_TARGET_TEMPERATURE:
if brightness is not None:
domain = entity.domain
service = SERVICE_SET_TEMPERATURE
data[ATTR_TEMPERATURE] = brightness
# If the requested entity is a media player, convert to volume
elif entity.domain == media_player.DOMAIN:
if entity_features & SUPPORT_VOLUME_SET:
@ -318,8 +333,9 @@ class HueOneLightChangeView(HomeAssistantView):
core.DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id},
blocking=True))
hass.async_create_task(hass.services.async_call(
domain, service, data, blocking=True))
if service is not None:
hass.async_create_task(hass.services.async_call(
domain, service, data, blocking=True))
json_response = \
[create_hue_success_response(entity_id, HUE_API_STATE_ON, result)]
@ -371,7 +387,7 @@ def parse_hue_api_put_light_body(request_json, entity):
elif entity.domain in [
script.DOMAIN, media_player.DOMAIN,
fan.DOMAIN, cover.DOMAIN]:
fan.DOMAIN, cover.DOMAIN, climate.DOMAIN]:
# Convert 0-255 to 0-100
level = brightness / 255 * 100
brightness = round(level)
@ -397,6 +413,10 @@ def get_entity_state(config, entity):
if entity_features & SUPPORT_BRIGHTNESS:
pass
elif entity.domain == climate.DOMAIN:
temperature = entity.attributes.get(ATTR_TEMPERATURE, 0)
# Convert 0-100 to 0-255
final_brightness = round(temperature * 255 / 100)
elif entity.domain == media_player.DOMAIN:
level = entity.attributes.get(
ATTR_MEDIA_VOLUME_LEVEL, 1.0 if final_state else 0.0)

View File

@ -11,7 +11,7 @@ from tests.common import get_test_instance_port
from homeassistant import core, const, setup
import homeassistant.components as core_components
from homeassistant.components import (
fan, http, light, script, emulated_hue, media_player, cover)
fan, http, light, script, emulated_hue, media_player, cover, climate)
from homeassistant.components.emulated_hue import Config
from homeassistant.components.emulated_hue.hue_api import (
HUE_API_STATE_ON, HUE_API_STATE_BRI, HueUsernameView, HueOneLightStateView,
@ -77,6 +77,15 @@ def hass_hue(loop, hass):
}
}))
loop.run_until_complete(
setup.async_setup_component(hass, climate.DOMAIN, {
'climate': [
{
'platform': 'demo',
}
]
}))
loop.run_until_complete(
setup.async_setup_component(hass, media_player.DOMAIN, {
'media_player': [
@ -136,6 +145,22 @@ def hass_hue(loop, hass):
cover_entity.entity_id, cover_entity.state, attributes=attrs
)
# Expose Hvac
hvac_entity = hass.states.get('climate.hvac')
attrs = dict(hvac_entity.attributes)
attrs[emulated_hue.ATTR_EMULATED_HUE_HIDDEN] = False
hass.states.async_set(
hvac_entity.entity_id, hvac_entity.state, attributes=attrs
)
# Expose HeatPump
hp_entity = hass.states.get('climate.heatpump')
attrs = dict(hp_entity.attributes)
attrs[emulated_hue.ATTR_EMULATED_HUE_HIDDEN] = False
hass.states.async_set(
hp_entity.entity_id, hp_entity.state, attributes=attrs
)
return hass
@ -189,6 +214,9 @@ def test_discover_lights(hue_client):
assert 'fan.living_room_fan' in devices
assert 'fan.ceiling_fan' not in devices
assert 'cover.living_room_window' in devices
assert 'climate.hvac' in devices
assert 'climate.heatpump' in devices
assert 'climate.ecobee' not in devices
@asyncio.coroutine
@ -316,6 +344,84 @@ def test_put_light_state_script(hass_hue, hue_client):
assert kitchen_light.attributes[light.ATTR_BRIGHTNESS] == level
@asyncio.coroutine
def test_put_light_state_climate_set_temperature(hass_hue, hue_client):
"""Test setting climate temperature."""
brightness = 19
temperature = round(brightness / 255 * 100)
hvac_result = yield from perform_put_light_state(
hass_hue, hue_client,
'climate.hvac', True, brightness)
hvac_result_json = yield from hvac_result.json()
assert hvac_result.status == 200
assert len(hvac_result_json) == 2
hvac = hass_hue.states.get('climate.hvac')
assert hvac.state == climate.const.STATE_COOL
assert hvac.attributes[climate.ATTR_TEMPERATURE] == temperature
assert hvac.attributes[climate.ATTR_OPERATION_MODE] == \
climate.const.STATE_COOL
# Make sure we can't change the ecobee temperature since it's not exposed
ecobee_result = yield from perform_put_light_state(
hass_hue, hue_client,
'climate.ecobee', True)
assert ecobee_result.status == 404
@asyncio.coroutine
def test_put_light_state_climate_turn_on(hass_hue, hue_client):
"""Test inability to turn climate on."""
yield from hass_hue.services.async_call(
climate.DOMAIN, const.SERVICE_TURN_OFF,
{const.ATTR_ENTITY_ID: 'climate.heatpump'},
blocking=True)
# Somehow after calling the above service the device gets unexposed,
# so we need to expose it again
hp_entity = hass_hue.states.get('climate.heatpump')
attrs = dict(hp_entity.attributes)
attrs[emulated_hue.ATTR_EMULATED_HUE_HIDDEN] = False
hass_hue.states.async_set(
hp_entity.entity_id, hp_entity.state, attributes=attrs
)
hp_result = yield from perform_put_light_state(
hass_hue, hue_client,
'climate.heatpump', True)
hp_result_json = yield from hp_result.json()
assert hp_result.status == 200
assert len(hp_result_json) == 1
hp = hass_hue.states.get('climate.heatpump')
assert hp.state == STATE_OFF
assert hp.attributes[climate.ATTR_OPERATION_MODE] == \
climate.const.STATE_HEAT
@asyncio.coroutine
def test_put_light_state_climate_turn_off(hass_hue, hue_client):
"""Test inability to turn climate off."""
hp_result = yield from perform_put_light_state(
hass_hue, hue_client,
'climate.heatpump', False)
hp_result_json = yield from hp_result.json()
assert hp_result.status == 200
assert len(hp_result_json) == 1
hp = hass_hue.states.get('climate.heatpump')
assert hp.state == climate.const.STATE_HEAT
assert hp.attributes[climate.ATTR_OPERATION_MODE] == \
climate.const.STATE_HEAT
@asyncio.coroutine
def test_put_light_state_media_player(hass_hue, hue_client):
"""Test turning on media player and setting volume."""