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:
parent
ef4498ec27
commit
c9de2f015b
2 changed files with 79 additions and 6 deletions
|
@ -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:
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Add table
Reference in a new issue