HomeKit - Climate: power state on/off support (#14082)

* add power state  support on off
* Added check for current operation mode
* Extended 'set_heat_cool'
* Added tests
This commit is contained in:
roiff 2018-05-04 00:22:43 +08:00 committed by cdce8p
parent ef4498ec27
commit c9de2f015b
2 changed files with 79 additions and 6 deletions

View file

@ -5,10 +5,10 @@ from homeassistant.components.climate import (
ATTR_CURRENT_TEMPERATURE, ATTR_TEMPERATURE,
ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW,
ATTR_OPERATION_MODE, ATTR_OPERATION_LIST,
STATE_HEAT, STATE_COOL, STATE_AUTO,
STATE_HEAT, STATE_COOL, STATE_AUTO, SUPPORT_ON_OFF,
SUPPORT_TARGET_TEMPERATURE_HIGH, SUPPORT_TARGET_TEMPERATURE_LOW)
from homeassistant.const import (
ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT,
ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT,
STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT)
from . import TYPES
@ -41,6 +41,7 @@ class Thermostat(HomeAccessory):
"""Initialize a Thermostat accessory object."""
super().__init__(*args, category=CATEGORY_THERMOSTAT)
self._unit = TEMP_CELSIUS
self.support_power_state = False
self.heat_cool_flag_target_state = False
self.temperature_flag_target_state = False
self.coolingthresh_flag_target_state = False
@ -50,6 +51,8 @@ class Thermostat(HomeAccessory):
self.chars = []
features = self.hass.states.get(self.entity_id) \
.attributes.get(ATTR_SUPPORTED_FEATURES)
if features & SUPPORT_ON_OFF:
self.support_power_state = True
if features & SUPPORT_TEMP_RANGE:
self.chars.extend((CHAR_COOLING_THRESHOLD_TEMPERATURE,
CHAR_HEATING_THRESHOLD_TEMPERATURE))
@ -93,6 +96,13 @@ class Thermostat(HomeAccessory):
_LOGGER.debug('%s: Set heat-cool to %d', self.entity_id, value)
self.heat_cool_flag_target_state = True
hass_value = HC_HOMEKIT_TO_HASS[value]
if self.support_power_state is True:
params = {ATTR_ENTITY_ID: self.entity_id}
if hass_value == STATE_OFF:
self.hass.services.call('climate', 'turn_off', params)
return
else:
self.hass.services.call('climate', 'turn_on', params)
self.hass.components.climate.set_operation_mode(
operation_mode=hass_value, entity_id=self.entity_id)
@ -178,15 +188,19 @@ class Thermostat(HomeAccessory):
# Update target operation mode
operation_mode = new_state.attributes.get(ATTR_OPERATION_MODE)
if operation_mode \
and operation_mode in HC_HASS_TO_HOMEKIT:
if self.support_power_state is True and new_state.state == STATE_OFF:
self.char_target_heat_cool.set_value(
HC_HASS_TO_HOMEKIT[STATE_OFF])
elif operation_mode and operation_mode in HC_HASS_TO_HOMEKIT:
if not self.heat_cool_flag_target_state:
self.char_target_heat_cool.set_value(
HC_HASS_TO_HOMEKIT[operation_mode])
self.heat_cool_flag_target_state = False
# Set current operation mode based on temperatures and target mode
if operation_mode == STATE_HEAT:
if self.support_power_state is True and new_state.state == STATE_OFF:
current_operation_mode = STATE_OFF
elif operation_mode == STATE_HEAT:
if isinstance(target_temp, float) and current_temp < target_temp:
current_operation_mode = STATE_HEAT
else:

View file

@ -7,7 +7,7 @@ from homeassistant.components.climate import (
ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEMP_HIGH, ATTR_OPERATION_MODE,
ATTR_OPERATION_LIST, STATE_COOL, STATE_HEAT, STATE_AUTO)
from homeassistant.const import (
ATTR_SERVICE, ATTR_SERVICE_DATA, ATTR_SUPPORTED_FEATURES,
ATTR_ENTITY_ID, ATTR_SERVICE, ATTR_SERVICE_DATA, ATTR_SUPPORTED_FEATURES,
ATTR_UNIT_OF_MEASUREMENT, EVENT_CALL_SERVICE,
STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT)
@ -261,6 +261,65 @@ class TestHomekitThermostats(unittest.TestCase):
25.0)
self.assertEqual(acc.char_cooling_thresh_temp.value, 25.0)
def test_power_state(self):
"""Test if accessory and HA are updated accordingly."""
climate = 'climate.test'
# SUPPORT_ON_OFF = True
self.hass.states.set(climate, STATE_HEAT,
{ATTR_SUPPORTED_FEATURES: 4096,
ATTR_OPERATION_MODE: STATE_HEAT,
ATTR_TEMPERATURE: 23.0,
ATTR_CURRENT_TEMPERATURE: 18.0})
self.hass.block_till_done()
acc = self.thermostat_cls(self.hass, 'Climate', climate,
2, config=None)
acc.run()
self.assertTrue(acc.support_power_state)
self.assertEqual(acc.char_current_heat_cool.value, 1)
self.assertEqual(acc.char_target_heat_cool.value, 1)
self.hass.states.set(climate, STATE_OFF,
{ATTR_OPERATION_MODE: STATE_HEAT,
ATTR_TEMPERATURE: 23.0,
ATTR_CURRENT_TEMPERATURE: 18.0})
self.hass.block_till_done()
self.assertEqual(acc.char_current_heat_cool.value, 0)
self.assertEqual(acc.char_target_heat_cool.value, 0)
self.hass.states.set(climate, STATE_OFF,
{ATTR_OPERATION_MODE: STATE_OFF,
ATTR_TEMPERATURE: 23.0,
ATTR_CURRENT_TEMPERATURE: 18.0})
self.hass.block_till_done()
self.assertEqual(acc.char_current_heat_cool.value, 0)
self.assertEqual(acc.char_target_heat_cool.value, 0)
# Set from HomeKit
acc.char_target_heat_cool.client_update_value(1)
self.hass.block_till_done()
self.assertEqual(
self.events[0].data[ATTR_SERVICE], 'turn_on')
self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA][ATTR_ENTITY_ID],
climate)
self.assertEqual(
self.events[1].data[ATTR_SERVICE], 'set_operation_mode')
self.assertEqual(
self.events[1].data[ATTR_SERVICE_DATA][ATTR_OPERATION_MODE],
STATE_HEAT)
self.assertEqual(acc.char_target_heat_cool.value, 1)
acc.char_target_heat_cool.client_update_value(0)
self.hass.block_till_done()
self.assertEqual(
self.events[2].data[ATTR_SERVICE], 'turn_off')
self.assertEqual(
self.events[2].data[ATTR_SERVICE_DATA][ATTR_ENTITY_ID],
climate)
self.assertEqual(acc.char_target_heat_cool.value, 0)
def test_thermostat_fahrenheit(self):
"""Test if accessory and HA are updated accordingly."""
climate = 'climate.test'