mirror of
https://github.com/home-assistant/core.git
synced 2025-07-08 22:07:10 +00:00
Add water_heater support to HomeKit (#17614)
* Homekit add support for water_heater * Added tests
This commit is contained in:
parent
e343f5521c
commit
ff33cbd22f
@ -173,6 +173,9 @@ def get_accessory(hass, driver, state, aid, config):
|
||||
elif state.domain in ('automation', 'input_boolean', 'remote', 'script'):
|
||||
a_type = 'Switch'
|
||||
|
||||
elif state.domain == 'water_heater':
|
||||
a_type = 'WaterHeater'
|
||||
|
||||
if a_type is None:
|
||||
return None
|
||||
|
||||
|
@ -146,3 +146,7 @@ DEVICE_CLASS_WINDOW = 'window'
|
||||
# #### Thresholds ####
|
||||
THRESHOLD_CO = 25
|
||||
THRESHOLD_CO2 = 1000
|
||||
|
||||
# #### Default values ####
|
||||
DEFAULT_MIN_TEMP_WATER_HEATER = 40 # °C
|
||||
DEFAULT_MAX_TEMP_WATER_HEATER = 60 # °C
|
||||
|
@ -6,13 +6,18 @@ from pyhap.const import CATEGORY_THERMOSTAT
|
||||
from homeassistant.components.climate import (
|
||||
ATTR_CURRENT_TEMPERATURE, ATTR_MAX_TEMP, ATTR_MIN_TEMP,
|
||||
ATTR_OPERATION_LIST, ATTR_OPERATION_MODE,
|
||||
ATTR_TEMPERATURE, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW,
|
||||
DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP,
|
||||
DOMAIN, SERVICE_SET_TEMPERATURE, SERVICE_SET_OPERATION_MODE, STATE_AUTO,
|
||||
STATE_COOL, STATE_HEAT, SUPPORT_ON_OFF, SUPPORT_TARGET_TEMPERATURE_HIGH,
|
||||
SUPPORT_TARGET_TEMPERATURE_LOW)
|
||||
ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW,
|
||||
DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP, DOMAIN as DOMAIN_CLIMATE,
|
||||
SERVICE_SET_OPERATION_MODE as SERVICE_SET_OPERATION_MODE_THERMOSTAT,
|
||||
SERVICE_SET_TEMPERATURE as SERVICE_SET_TEMPERATURE_THERMOSTAT,
|
||||
STATE_AUTO, STATE_COOL, STATE_HEAT, SUPPORT_ON_OFF,
|
||||
SUPPORT_TARGET_TEMPERATURE_HIGH, SUPPORT_TARGET_TEMPERATURE_LOW)
|
||||
from homeassistant.components.water_heater import (
|
||||
DOMAIN as DOMAIN_WATER_HEATER,
|
||||
SERVICE_SET_TEMPERATURE as SERVICE_SET_TEMPERATURE_WATER_HEATER)
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, SERVICE_TURN_OFF, SERVICE_TURN_ON,
|
||||
ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_TEMPERATURE,
|
||||
SERVICE_TURN_OFF, SERVICE_TURN_ON,
|
||||
STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT)
|
||||
|
||||
from . import TYPES
|
||||
@ -21,7 +26,9 @@ from .const import (
|
||||
CHAR_COOLING_THRESHOLD_TEMPERATURE, CHAR_CURRENT_HEATING_COOLING,
|
||||
CHAR_CURRENT_TEMPERATURE, CHAR_TARGET_HEATING_COOLING,
|
||||
CHAR_HEATING_THRESHOLD_TEMPERATURE, CHAR_TARGET_TEMPERATURE,
|
||||
CHAR_TEMP_DISPLAY_UNITS, PROP_MAX_VALUE, PROP_MIN_VALUE, SERV_THERMOSTAT)
|
||||
CHAR_TEMP_DISPLAY_UNITS,
|
||||
DEFAULT_MAX_TEMP_WATER_HEATER, DEFAULT_MIN_TEMP_WATER_HEATER,
|
||||
PROP_MAX_VALUE, PROP_MIN_VALUE, SERV_THERMOSTAT)
|
||||
from .util import temperature_to_homekit, temperature_to_states
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -114,7 +121,7 @@ class Thermostat(HomeAccessory):
|
||||
return min_temp, max_temp
|
||||
|
||||
def set_heat_cool(self, value):
|
||||
"""Move operation mode to value if call came from HomeKit."""
|
||||
"""Change operation mode to value if call came from HomeKit."""
|
||||
if value in HC_HOMEKIT_TO_HASS:
|
||||
_LOGGER.debug('%s: Set heat-cool to %d', self.entity_id, value)
|
||||
self.heat_cool_flag_target_state = True
|
||||
@ -122,13 +129,14 @@ class Thermostat(HomeAccessory):
|
||||
if self.support_power_state is True:
|
||||
params = {ATTR_ENTITY_ID: self.entity_id}
|
||||
if hass_value == STATE_OFF:
|
||||
self.call_service(DOMAIN, SERVICE_TURN_OFF, params)
|
||||
self.call_service(DOMAIN_CLIMATE, SERVICE_TURN_OFF, params)
|
||||
return
|
||||
self.hass.services.call(DOMAIN, SERVICE_TURN_ON, params)
|
||||
self.call_service(DOMAIN_CLIMATE, SERVICE_TURN_ON, params)
|
||||
params = {ATTR_ENTITY_ID: self.entity_id,
|
||||
ATTR_OPERATION_MODE: hass_value}
|
||||
self.call_service(
|
||||
DOMAIN, SERVICE_SET_OPERATION_MODE, params, hass_value)
|
||||
DOMAIN_CLIMATE, SERVICE_SET_OPERATION_MODE_THERMOSTAT,
|
||||
params, hass_value)
|
||||
|
||||
@debounce
|
||||
def set_cooling_threshold(self, value):
|
||||
@ -142,9 +150,9 @@ class Thermostat(HomeAccessory):
|
||||
ATTR_ENTITY_ID: self.entity_id,
|
||||
ATTR_TARGET_TEMP_HIGH: temperature,
|
||||
ATTR_TARGET_TEMP_LOW: temperature_to_states(low, self._unit)}
|
||||
self.call_service(DOMAIN, SERVICE_SET_TEMPERATURE, params,
|
||||
"cooling threshold {}{}".format(temperature,
|
||||
self._unit))
|
||||
self.call_service(
|
||||
DOMAIN_CLIMATE, SERVICE_SET_TEMPERATURE_THERMOSTAT,
|
||||
params, 'cooling threshold {}{}'.format(temperature, self._unit))
|
||||
|
||||
@debounce
|
||||
def set_heating_threshold(self, value):
|
||||
@ -158,9 +166,9 @@ class Thermostat(HomeAccessory):
|
||||
ATTR_ENTITY_ID: self.entity_id,
|
||||
ATTR_TARGET_TEMP_HIGH: temperature_to_states(high, self._unit),
|
||||
ATTR_TARGET_TEMP_LOW: temperature}
|
||||
self.call_service(DOMAIN, SERVICE_SET_TEMPERATURE, params,
|
||||
"heating threshold {}{}".format(temperature,
|
||||
self._unit))
|
||||
self.call_service(
|
||||
DOMAIN_CLIMATE, SERVICE_SET_TEMPERATURE_THERMOSTAT,
|
||||
params, 'heating threshold {}{}'.format(temperature, self._unit))
|
||||
|
||||
@debounce
|
||||
def set_target_temperature(self, value):
|
||||
@ -172,12 +180,12 @@ class Thermostat(HomeAccessory):
|
||||
params = {
|
||||
ATTR_ENTITY_ID: self.entity_id,
|
||||
ATTR_TEMPERATURE: temperature}
|
||||
self.call_service(DOMAIN, SERVICE_SET_TEMPERATURE, params,
|
||||
"target {}{}".format(temperature,
|
||||
self._unit))
|
||||
self.call_service(
|
||||
DOMAIN_CLIMATE, SERVICE_SET_TEMPERATURE_THERMOSTAT,
|
||||
params, 'target {}{}'.format(temperature, self._unit))
|
||||
|
||||
def update_state(self, new_state):
|
||||
"""Update security state after state changed."""
|
||||
"""Update thermostat state after state changed."""
|
||||
# Update current temperature
|
||||
current_temp = new_state.attributes.get(ATTR_CURRENT_TEMPERATURE)
|
||||
if isinstance(current_temp, (int, float)):
|
||||
@ -268,3 +276,92 @@ class Thermostat(HomeAccessory):
|
||||
|
||||
self.char_current_heat_cool.set_value(
|
||||
HC_HASS_TO_HOMEKIT[current_operation_mode])
|
||||
|
||||
|
||||
@TYPES.register('WaterHeater')
|
||||
class WaterHeater(HomeAccessory):
|
||||
"""Generate a WaterHeater accessory for a water_heater."""
|
||||
|
||||
def __init__(self, *args):
|
||||
"""Initialize a WaterHeater accessory object."""
|
||||
super().__init__(*args, category=CATEGORY_THERMOSTAT)
|
||||
self._unit = self.hass.config.units.temperature_unit
|
||||
self.flag_heat_cool = False
|
||||
self.flag_temperature = False
|
||||
min_temp, max_temp = self.get_temperature_range()
|
||||
|
||||
serv_thermostat = self.add_preload_service(SERV_THERMOSTAT)
|
||||
|
||||
self.char_current_heat_cool = serv_thermostat.configure_char(
|
||||
CHAR_CURRENT_HEATING_COOLING, value=1)
|
||||
self.char_target_heat_cool = serv_thermostat.configure_char(
|
||||
CHAR_TARGET_HEATING_COOLING, value=1,
|
||||
setter_callback=self.set_heat_cool)
|
||||
|
||||
self.char_current_temp = serv_thermostat.configure_char(
|
||||
CHAR_CURRENT_TEMPERATURE, value=50.0)
|
||||
self.char_target_temp = serv_thermostat.configure_char(
|
||||
CHAR_TARGET_TEMPERATURE, value=50.0,
|
||||
properties={PROP_MIN_VALUE: min_temp,
|
||||
PROP_MAX_VALUE: max_temp},
|
||||
setter_callback=self.set_target_temperature)
|
||||
|
||||
self.char_display_units = serv_thermostat.configure_char(
|
||||
CHAR_TEMP_DISPLAY_UNITS, value=0)
|
||||
|
||||
def get_temperature_range(self):
|
||||
"""Return min and max temperature range."""
|
||||
max_temp = self.hass.states.get(self.entity_id) \
|
||||
.attributes.get(ATTR_MAX_TEMP)
|
||||
max_temp = temperature_to_homekit(max_temp, self._unit) if max_temp \
|
||||
else DEFAULT_MAX_TEMP_WATER_HEATER
|
||||
|
||||
min_temp = self.hass.states.get(self.entity_id) \
|
||||
.attributes.get(ATTR_MIN_TEMP)
|
||||
min_temp = temperature_to_homekit(min_temp, self._unit) if min_temp \
|
||||
else DEFAULT_MIN_TEMP_WATER_HEATER
|
||||
|
||||
return min_temp, max_temp
|
||||
|
||||
def set_heat_cool(self, value):
|
||||
"""Change operation mode to value if call came from HomeKit."""
|
||||
_LOGGER.debug('%s: Set heat-cool to %d', self.entity_id, value)
|
||||
self.flag_heat_cool = True
|
||||
hass_value = HC_HOMEKIT_TO_HASS[value]
|
||||
if hass_value != STATE_HEAT:
|
||||
self.char_target_heat_cool.set_value(1) # Heat
|
||||
|
||||
@debounce
|
||||
def set_target_temperature(self, value):
|
||||
"""Set target temperature to value if call came from HomeKit."""
|
||||
_LOGGER.debug('%s: Set target temperature to %.2f°C',
|
||||
self.entity_id, value)
|
||||
self.flag_temperature = True
|
||||
temperature = temperature_to_states(value, self._unit)
|
||||
params = {
|
||||
ATTR_ENTITY_ID: self.entity_id,
|
||||
ATTR_TEMPERATURE: temperature}
|
||||
self.call_service(
|
||||
DOMAIN_WATER_HEATER, SERVICE_SET_TEMPERATURE_WATER_HEATER,
|
||||
params, 'target {}{}'.format(temperature, self._unit))
|
||||
|
||||
def update_state(self, new_state):
|
||||
"""Update water_heater state after state change."""
|
||||
# Update current and target temperature
|
||||
temperature = new_state.attributes.get(ATTR_TEMPERATURE)
|
||||
if isinstance(temperature, (int, float)):
|
||||
temperature = temperature_to_homekit(temperature, self._unit)
|
||||
self.char_current_temp.set_value(temperature)
|
||||
if not self.flag_temperature:
|
||||
self.char_target_temp.set_value(temperature)
|
||||
self.flag_temperature = False
|
||||
|
||||
# Update display units
|
||||
if self._unit and self._unit in UNIT_HASS_TO_HOMEKIT:
|
||||
self.char_display_units.set_value(UNIT_HASS_TO_HOMEKIT[self._unit])
|
||||
|
||||
# Update target operation mode
|
||||
operation_mode = new_state.attributes.get(ATTR_OPERATION_MODE)
|
||||
if operation_mode and not self.flag_heat_cool:
|
||||
self.char_target_heat_cool.set_value(1) # Heat
|
||||
self.flag_heat_cool = False
|
||||
|
@ -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."""
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user