Add water_heater support to HomeKit (#17614)

* Homekit add support for water_heater
* Added tests
This commit is contained in:
cdce8p
2018-10-19 21:04:05 +02:00
committed by GitHub
parent e343f5521c
commit ff33cbd22f
5 changed files with 281 additions and 52 deletions
@@ -69,6 +69,7 @@ def test_customize_options(config, name):
('Thermostat', 'climate.test', 'auto',
{ATTR_SUPPORTED_FEATURES: climate.SUPPORT_TARGET_TEMPERATURE_LOW |
climate.SUPPORT_TARGET_TEMPERATURE_HIGH}, {}),
('WaterHeater', 'water_heater.test', 'auto', {}, {}),
])
def test_types(type_name, entity_id, state, attrs, config):
"""Test if types are associated correctly."""
+155 -31
View File
@@ -5,15 +5,18 @@ from unittest.mock import patch
import pytest
from homeassistant.components.climate import (
ATTR_CURRENT_TEMPERATURE, ATTR_MAX_TEMP, ATTR_MIN_TEMP, ATTR_TEMPERATURE,
ATTR_CURRENT_TEMPERATURE, ATTR_MAX_TEMP, ATTR_MIN_TEMP,
ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEMP_HIGH, ATTR_OPERATION_MODE,
ATTR_OPERATION_LIST, DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP, DOMAIN,
STATE_AUTO, STATE_COOL, STATE_HEAT)
ATTR_OPERATION_LIST, DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP,
DOMAIN as DOMAIN_CLIMATE, STATE_AUTO, STATE_COOL, STATE_HEAT)
from homeassistant.components.homekit.const import (
ATTR_VALUE, PROP_MAX_VALUE, PROP_MIN_VALUE)
ATTR_VALUE, DEFAULT_MAX_TEMP_WATER_HEATER, DEFAULT_MIN_TEMP_WATER_HEATER,
PROP_MAX_VALUE, PROP_MIN_VALUE)
from homeassistant.components.water_heater import (
DOMAIN as DOMAIN_WATER_HEATER)
from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, CONF_TEMPERATURE_UNIT, STATE_OFF,
TEMP_FAHRENHEIT)
ATTR_ENTITY_ID, ATTR_TEMPERATURE, 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
@@ -25,13 +28,14 @@ def cls():
patcher = patch_debounce()
patcher.start()
_import = __import__('homeassistant.components.homekit.type_thermostats',
fromlist=['Thermostat'])
patcher_tuple = namedtuple('Cls', ['thermostat'])
yield patcher_tuple(thermostat=_import.Thermostat)
fromlist=['Thermostat', 'WaterHeater'])
patcher_tuple = namedtuple('Cls', ['thermostat', 'water_heater'])
yield patcher_tuple(thermostat=_import.Thermostat,
water_heater=_import.WaterHeater)
patcher.stop()
async def test_default_thermostat(hass, hk_driver, cls, events):
async def test_thermostat(hass, hk_driver, cls, events):
"""Test if accessory and HA are updated accordingly."""
entity_id = 'climate.test'
@@ -147,8 +151,9 @@ async def test_default_thermostat(hass, hk_driver, cls, events):
assert acc.char_display_units.value == 0
# Set from HomeKit
call_set_temperature = async_mock_service(hass, DOMAIN, 'set_temperature')
call_set_operation_mode = async_mock_service(hass, DOMAIN,
call_set_temperature = async_mock_service(hass, DOMAIN_CLIMATE,
'set_temperature')
call_set_operation_mode = async_mock_service(hass, DOMAIN_CLIMATE,
'set_operation_mode')
await hass.async_add_job(acc.char_target_temp.client_update_value, 19.0)
@@ -158,8 +163,7 @@ async def test_default_thermostat(hass, hk_driver, cls, events):
assert call_set_temperature[0].data[ATTR_TEMPERATURE] == 19.0
assert acc.char_target_temp.value == 19.0
assert len(events) == 1
assert events[-1].data[ATTR_VALUE] == "target {}°C".format(
acc.char_target_temp.value)
assert events[-1].data[ATTR_VALUE] == 'target 19.0°C'
await hass.async_add_job(acc.char_target_heat_cool.client_update_value, 1)
await hass.async_block_till_done()
@@ -171,7 +175,7 @@ async def test_default_thermostat(hass, hk_driver, cls, events):
assert events[-1].data[ATTR_VALUE] == STATE_HEAT
async def test_auto_thermostat(hass, hk_driver, cls, events):
async def test_thermostat_auto(hass, hk_driver, cls, events):
"""Test if accessory and HA are updated accordingly."""
entity_id = 'climate.test'
@@ -234,7 +238,8 @@ async def test_auto_thermostat(hass, hk_driver, cls, events):
assert acc.char_display_units.value == 0
# Set from HomeKit
call_set_temperature = async_mock_service(hass, DOMAIN, 'set_temperature')
call_set_temperature = async_mock_service(hass, DOMAIN_CLIMATE,
'set_temperature')
await hass.async_add_job(
acc.char_heating_thresh_temp.client_update_value, 20.0)
@@ -244,8 +249,7 @@ async def test_auto_thermostat(hass, hk_driver, cls, events):
assert call_set_temperature[0].data[ATTR_TARGET_TEMP_LOW] == 20.0
assert acc.char_heating_thresh_temp.value == 20.0
assert len(events) == 1
assert events[-1].data[ATTR_VALUE] == "heating threshold {}°C".format(
acc.char_heating_thresh_temp.value)
assert events[-1].data[ATTR_VALUE] == 'heating threshold 20.0°C'
await hass.async_add_job(
acc.char_cooling_thresh_temp.client_update_value, 25.0)
@@ -255,11 +259,10 @@ async def test_auto_thermostat(hass, hk_driver, cls, events):
assert call_set_temperature[1].data[ATTR_TARGET_TEMP_HIGH] == 25.0
assert acc.char_cooling_thresh_temp.value == 25.0
assert len(events) == 2
assert events[-1].data[ATTR_VALUE] == "cooling threshold {}°C".format(
acc.char_cooling_thresh_temp.value)
assert events[-1].data[ATTR_VALUE] == 'cooling threshold 25.0°C'
async def test_power_state(hass, hk_driver, cls, events):
async def test_thermostat_power_state(hass, hk_driver, cls, events):
"""Test if accessory and HA are updated accordingly."""
entity_id = 'climate.test'
@@ -295,9 +298,9 @@ async def test_power_state(hass, hk_driver, cls, events):
assert acc.char_target_heat_cool.value == 0
# Set from HomeKit
call_turn_on = async_mock_service(hass, DOMAIN, 'turn_on')
call_turn_off = async_mock_service(hass, DOMAIN, 'turn_off')
call_set_operation_mode = async_mock_service(hass, DOMAIN,
call_turn_on = async_mock_service(hass, DOMAIN_CLIMATE, 'turn_on')
call_turn_off = async_mock_service(hass, DOMAIN_CLIMATE, 'turn_off')
call_set_operation_mode = async_mock_service(hass, DOMAIN_CLIMATE,
'set_operation_mode')
await hass.async_add_job(acc.char_target_heat_cool.client_update_value, 1)
@@ -308,7 +311,7 @@ async def test_power_state(hass, hk_driver, cls, events):
assert call_set_operation_mode[0].data[ATTR_ENTITY_ID] == entity_id
assert call_set_operation_mode[0].data[ATTR_OPERATION_MODE] == STATE_HEAT
assert acc.char_target_heat_cool.value == 1
assert len(events) == 1
assert len(events) == 2
assert events[-1].data[ATTR_VALUE] == STATE_HEAT
await hass.async_add_job(acc.char_target_heat_cool.client_update_value, 0)
@@ -316,7 +319,7 @@ async def test_power_state(hass, hk_driver, cls, events):
assert call_turn_off
assert call_turn_off[0].data[ATTR_ENTITY_ID] == entity_id
assert acc.char_target_heat_cool.value == 0
assert len(events) == 2
assert len(events) == 3
assert events[-1].data[ATTR_VALUE] is None
@@ -347,7 +350,8 @@ async def test_thermostat_fahrenheit(hass, hk_driver, cls, events):
assert acc.char_display_units.value == 1
# Set from HomeKit
call_set_temperature = async_mock_service(hass, DOMAIN, 'set_temperature')
call_set_temperature = async_mock_service(hass, DOMAIN_CLIMATE,
'set_temperature')
await hass.async_add_job(
acc.char_cooling_thresh_temp.client_update_value, 23)
@@ -357,7 +361,7 @@ async def test_thermostat_fahrenheit(hass, hk_driver, cls, events):
assert call_set_temperature[0].data[ATTR_TARGET_TEMP_HIGH] == 73.4
assert call_set_temperature[0].data[ATTR_TARGET_TEMP_LOW] == 68
assert len(events) == 1
assert events[-1].data[ATTR_VALUE] == "cooling threshold 73.4°F"
assert events[-1].data[ATTR_VALUE] == 'cooling threshold 73.4°F'
await hass.async_add_job(
acc.char_heating_thresh_temp.client_update_value, 22)
@@ -367,7 +371,7 @@ async def test_thermostat_fahrenheit(hass, hk_driver, cls, events):
assert call_set_temperature[1].data[ATTR_TARGET_TEMP_HIGH] == 73.4
assert call_set_temperature[1].data[ATTR_TARGET_TEMP_LOW] == 71.6
assert len(events) == 2
assert events[-1].data[ATTR_VALUE] == "heating threshold 71.6°F"
assert events[-1].data[ATTR_VALUE] == 'heating threshold 71.6°F'
await hass.async_add_job(acc.char_target_temp.client_update_value, 24.0)
await hass.async_block_till_done()
@@ -375,10 +379,10 @@ async def test_thermostat_fahrenheit(hass, hk_driver, cls, events):
assert call_set_temperature[2].data[ATTR_ENTITY_ID] == entity_id
assert call_set_temperature[2].data[ATTR_TEMPERATURE] == 75.2
assert len(events) == 3
assert events[-1].data[ATTR_VALUE] == "target 75.2°F"
assert events[-1].data[ATTR_VALUE] == 'target 75.2°F'
async def test_get_temperature_range(hass, hk_driver, cls):
async def test_thermostat_get_temperature_range(hass, hk_driver, cls):
"""Test if temperature range is evaluated correctly."""
entity_id = 'climate.test'
@@ -396,3 +400,123 @@ async def test_get_temperature_range(hass, hk_driver, cls):
{ATTR_MIN_TEMP: 60, ATTR_MAX_TEMP: 70})
await hass.async_block_till_done()
assert acc.get_temperature_range() == (15.6, 21.1)
async def test_water_heater(hass, hk_driver, cls, events):
"""Test if accessory and HA are updated accordingly."""
entity_id = 'water_heater.test'
hass.states.async_set(entity_id, STATE_HEAT)
await hass.async_block_till_done()
acc = cls.water_heater(hass, hk_driver, 'WaterHeater', entity_id, 2, None)
await hass.async_add_job(acc.run)
await hass.async_block_till_done()
assert acc.aid == 2
assert acc.category == 9 # Thermostat
assert acc.char_current_heat_cool.value == 1 # Heat
assert acc.char_target_heat_cool.value == 1 # Heat
assert acc.char_current_temp.value == 50.0
assert acc.char_target_temp.value == 50.0
assert acc.char_display_units.value == 0
assert acc.char_target_temp.properties[PROP_MAX_VALUE] == \
DEFAULT_MAX_TEMP_WATER_HEATER
assert acc.char_target_temp.properties[PROP_MIN_VALUE] == \
DEFAULT_MIN_TEMP_WATER_HEATER
hass.states.async_set(entity_id, STATE_HEAT,
{ATTR_OPERATION_MODE: STATE_HEAT,
ATTR_TEMPERATURE: 56.0})
await hass.async_block_till_done()
assert acc.char_target_temp.value == 56.0
assert acc.char_current_temp.value == 56.0
assert acc.char_target_heat_cool.value == 1
assert acc.char_current_heat_cool.value == 1
assert acc.char_display_units.value == 0
hass.states.async_set(entity_id, STATE_AUTO,
{ATTR_OPERATION_MODE: STATE_AUTO})
await hass.async_block_till_done()
assert acc.char_target_heat_cool.value == 1
assert acc.char_current_heat_cool.value == 1
# Set from HomeKit
call_set_temperature = async_mock_service(hass, DOMAIN_WATER_HEATER,
'set_temperature')
await hass.async_add_job(acc.char_target_temp.client_update_value, 52.0)
await hass.async_block_till_done()
assert call_set_temperature
assert call_set_temperature[0].data[ATTR_ENTITY_ID] == entity_id
assert call_set_temperature[0].data[ATTR_TEMPERATURE] == 52.0
assert acc.char_target_temp.value == 52.0
assert len(events) == 1
assert events[-1].data[ATTR_VALUE] == 'target 52.0°C'
await hass.async_add_job(acc.char_target_heat_cool.client_update_value, 0)
await hass.async_block_till_done()
assert acc.char_target_heat_cool.value == 1
await hass.async_add_job(acc.char_target_heat_cool.client_update_value, 2)
await hass.async_block_till_done()
assert acc.char_target_heat_cool.value == 1
await hass.async_add_job(acc.char_target_heat_cool.client_update_value, 3)
await hass.async_block_till_done()
assert acc.char_target_heat_cool.value == 1
async def test_water_heater_fahrenheit(hass, hk_driver, cls, events):
"""Test if accessory and HA are update accordingly."""
entity_id = 'water_heater.test'
hass.states.async_set(entity_id, STATE_HEAT)
await hass.async_block_till_done()
with patch.object(hass.config.units, CONF_TEMPERATURE_UNIT,
new=TEMP_FAHRENHEIT):
acc = cls.water_heater(hass, hk_driver, 'WaterHeater',
entity_id, 2, None)
await hass.async_add_job(acc.run)
await hass.async_block_till_done()
hass.states.async_set(entity_id, STATE_HEAT,
{ATTR_TEMPERATURE: 131})
await hass.async_block_till_done()
assert acc.char_target_temp.value == 55.0
assert acc.char_current_temp.value == 55.0
assert acc.char_display_units.value == 1
# Set from HomeKit
call_set_temperature = async_mock_service(hass, DOMAIN_WATER_HEATER,
'set_temperature')
await hass.async_add_job(acc.char_target_temp.client_update_value, 60)
await hass.async_block_till_done()
assert call_set_temperature
assert call_set_temperature[0].data[ATTR_ENTITY_ID] == entity_id
assert call_set_temperature[0].data[ATTR_TEMPERATURE] == 140.0
assert acc.char_target_temp.value == 60.0
assert len(events) == 1
assert events[-1].data[ATTR_VALUE] == 'target 140.0°F'
async def test_water_heater_get_temperature_range(hass, hk_driver, cls):
"""Test if temperature range is evaluated correctly."""
entity_id = 'water_heater.test'
hass.states.async_set(entity_id, STATE_HEAT)
await hass.async_block_till_done()
acc = cls.thermostat(hass, hk_driver, 'Climate', entity_id, 2, None)
hass.states.async_set(entity_id, STATE_HEAT,
{ATTR_MIN_TEMP: 20, ATTR_MAX_TEMP: 25})
await hass.async_block_till_done()
assert acc.get_temperature_range() == (20, 25)
acc._unit = TEMP_FAHRENHEIT
hass.states.async_set(entity_id, STATE_OFF,
{ATTR_MIN_TEMP: 60, ATTR_MAX_TEMP: 70})
await hass.async_block_till_done()
assert acc.get_temperature_range() == (15.6, 21.1)