mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
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
@ -5,10 +5,10 @@ from homeassistant.components.climate import (
|
|||||||
ATTR_CURRENT_TEMPERATURE, ATTR_TEMPERATURE,
|
ATTR_CURRENT_TEMPERATURE, ATTR_TEMPERATURE,
|
||||||
ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW,
|
ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW,
|
||||||
ATTR_OPERATION_MODE, ATTR_OPERATION_LIST,
|
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)
|
SUPPORT_TARGET_TEMPERATURE_HIGH, SUPPORT_TARGET_TEMPERATURE_LOW)
|
||||||
from homeassistant.const import (
|
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)
|
STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT)
|
||||||
|
|
||||||
from . import TYPES
|
from . import TYPES
|
||||||
@ -41,6 +41,7 @@ class Thermostat(HomeAccessory):
|
|||||||
"""Initialize a Thermostat accessory object."""
|
"""Initialize a Thermostat accessory object."""
|
||||||
super().__init__(*args, category=CATEGORY_THERMOSTAT)
|
super().__init__(*args, category=CATEGORY_THERMOSTAT)
|
||||||
self._unit = TEMP_CELSIUS
|
self._unit = TEMP_CELSIUS
|
||||||
|
self.support_power_state = False
|
||||||
self.heat_cool_flag_target_state = False
|
self.heat_cool_flag_target_state = False
|
||||||
self.temperature_flag_target_state = False
|
self.temperature_flag_target_state = False
|
||||||
self.coolingthresh_flag_target_state = False
|
self.coolingthresh_flag_target_state = False
|
||||||
@ -50,6 +51,8 @@ class Thermostat(HomeAccessory):
|
|||||||
self.chars = []
|
self.chars = []
|
||||||
features = self.hass.states.get(self.entity_id) \
|
features = self.hass.states.get(self.entity_id) \
|
||||||
.attributes.get(ATTR_SUPPORTED_FEATURES)
|
.attributes.get(ATTR_SUPPORTED_FEATURES)
|
||||||
|
if features & SUPPORT_ON_OFF:
|
||||||
|
self.support_power_state = True
|
||||||
if features & SUPPORT_TEMP_RANGE:
|
if features & SUPPORT_TEMP_RANGE:
|
||||||
self.chars.extend((CHAR_COOLING_THRESHOLD_TEMPERATURE,
|
self.chars.extend((CHAR_COOLING_THRESHOLD_TEMPERATURE,
|
||||||
CHAR_HEATING_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)
|
_LOGGER.debug('%s: Set heat-cool to %d', self.entity_id, value)
|
||||||
self.heat_cool_flag_target_state = True
|
self.heat_cool_flag_target_state = True
|
||||||
hass_value = HC_HOMEKIT_TO_HASS[value]
|
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(
|
self.hass.components.climate.set_operation_mode(
|
||||||
operation_mode=hass_value, entity_id=self.entity_id)
|
operation_mode=hass_value, entity_id=self.entity_id)
|
||||||
|
|
||||||
@ -178,15 +188,19 @@ class Thermostat(HomeAccessory):
|
|||||||
|
|
||||||
# Update target operation mode
|
# Update target operation mode
|
||||||
operation_mode = new_state.attributes.get(ATTR_OPERATION_MODE)
|
operation_mode = new_state.attributes.get(ATTR_OPERATION_MODE)
|
||||||
if operation_mode \
|
if self.support_power_state is True and new_state.state == STATE_OFF:
|
||||||
and operation_mode in HC_HASS_TO_HOMEKIT:
|
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:
|
if not self.heat_cool_flag_target_state:
|
||||||
self.char_target_heat_cool.set_value(
|
self.char_target_heat_cool.set_value(
|
||||||
HC_HASS_TO_HOMEKIT[operation_mode])
|
HC_HASS_TO_HOMEKIT[operation_mode])
|
||||||
self.heat_cool_flag_target_state = False
|
self.heat_cool_flag_target_state = False
|
||||||
|
|
||||||
# Set current operation mode based on temperatures and target mode
|
# 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:
|
if isinstance(target_temp, float) and current_temp < target_temp:
|
||||||
current_operation_mode = STATE_HEAT
|
current_operation_mode = STATE_HEAT
|
||||||
else:
|
else:
|
||||||
|
@ -7,7 +7,7 @@ from homeassistant.components.climate import (
|
|||||||
ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEMP_HIGH, ATTR_OPERATION_MODE,
|
ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEMP_HIGH, ATTR_OPERATION_MODE,
|
||||||
ATTR_OPERATION_LIST, STATE_COOL, STATE_HEAT, STATE_AUTO)
|
ATTR_OPERATION_LIST, STATE_COOL, STATE_HEAT, STATE_AUTO)
|
||||||
from homeassistant.const import (
|
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,
|
ATTR_UNIT_OF_MEASUREMENT, EVENT_CALL_SERVICE,
|
||||||
STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT)
|
STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT)
|
||||||
|
|
||||||
@ -261,6 +261,65 @@ class TestHomekitThermostats(unittest.TestCase):
|
|||||||
25.0)
|
25.0)
|
||||||
self.assertEqual(acc.char_cooling_thresh_temp.value, 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):
|
def test_thermostat_fahrenheit(self):
|
||||||
"""Test if accessory and HA are updated accordingly."""
|
"""Test if accessory and HA are updated accordingly."""
|
||||||
climate = 'climate.test'
|
climate = 'climate.test'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user