Allow emulated hue to set climate component temperature (#19034)
parent
5debc8828a
commit
77dc7595ee
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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."""
|
||||
|
|
Loading…
Reference in New Issue