1
mirror of https://github.com/home-assistant/core synced 2024-09-09 12:51:22 +02:00

Allow HomeKit name to be customized (#14159)

This commit is contained in:
Matt Schmitt 2018-05-11 08:22:45 -04:00 committed by cdce8p
parent 48d70e520f
commit 621c653fed
20 changed files with 97 additions and 79 deletions

View File

@ -12,20 +12,19 @@ import voluptuous as vol
from homeassistant.components.cover import (
SUPPORT_CLOSE, SUPPORT_OPEN, SUPPORT_SET_POSITION)
from homeassistant.const import (
ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT,
ATTR_DEVICE_CLASS, CONF_IP_ADDRESS, CONF_PORT, TEMP_CELSIUS,
TEMP_FAHRENHEIT, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
ATTR_DEVICE_CLASS, ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT,
CONF_IP_ADDRESS, CONF_NAME, CONF_PORT, TEMP_CELSIUS, TEMP_FAHRENHEIT,
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_TEMPERATURE)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entityfilter import FILTER_SCHEMA
from homeassistant.util import get_local_ip
from homeassistant.util.decorator import Registry
from .const import (
DOMAIN, HOMEKIT_FILE, CONF_AUTO_START, CONF_ENTITY_CONFIG, CONF_FILTER,
DEFAULT_PORT, DEFAULT_AUTO_START, SERVICE_HOMEKIT_START,
CONF_AUTO_START, CONF_ENTITY_CONFIG, CONF_FILTER, DEFAULT_PORT,
DEFAULT_AUTO_START, DOMAIN, HOMEKIT_FILE, SERVICE_HOMEKIT_START,
DEVICE_CLASS_CO2, DEVICE_CLASS_PM25)
from .util import (
validate_entity_config, show_setup_message)
from .util import show_setup_message, validate_entity_config
TYPES = Registry()
_LOGGER = logging.getLogger(__name__)
@ -93,7 +92,7 @@ def get_accessory(hass, state, aid, config):
return None
a_type = None
config = config or {}
name = config.get(CONF_NAME, state.name)
if state.domain == 'alarm_control_panel':
a_type = 'SecuritySystem'
@ -147,7 +146,7 @@ def get_accessory(hass, state, aid, config):
return None
_LOGGER.debug('Add "%s" as "%s"', state.entity_id, a_type)
return TYPES[a_type](hass, state.name, state.entity_id, aid, config=config)
return TYPES[a_type](hass, name, state.entity_id, aid, config)
def generate_aid(entity_id):

View File

@ -16,8 +16,8 @@ from homeassistant.helpers.event import (
from homeassistant.util import dt as dt_util
from .const import (
DEBOUNCE_TIMEOUT, BRIDGE_MODEL, BRIDGE_NAME,
BRIDGE_SERIAL_NUMBER, MANUFACTURER)
BRIDGE_MODEL, BRIDGE_NAME, BRIDGE_SERIAL_NUMBER,
DEBOUNCE_TIMEOUT, MANUFACTURER)
from .util import (
show_setup_message, dismiss_setup_message)
@ -64,14 +64,16 @@ def debounce(func):
class HomeAccessory(Accessory):
"""Adapter class for Accessory."""
def __init__(self, hass, name, entity_id, aid, category=CATEGORY_OTHER):
def __init__(self, hass, name, entity_id, aid, config,
category=CATEGORY_OTHER):
"""Initialize a Accessory object."""
super().__init__(name, aid=aid)
domain = split_entity_id(entity_id)[0].replace("_", " ").title()
model = split_entity_id(entity_id)[0].replace("_", " ").title()
self.set_info_service(
firmware_revision=__version__, manufacturer=MANUFACTURER,
model=domain, serial_number=entity_id)
model=model, serial_number=entity_id)
self.category = category
self.config = config
self.entity_id = entity_id
self.hass = hass

View File

@ -28,7 +28,7 @@ class GarageDoorOpener(HomeAccessory):
and support no more than open, close, and stop.
"""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a GarageDoorOpener accessory object."""
super().__init__(*args, category=CATEGORY_GARAGE_DOOR_OPENER)
self.flag_target_state = False
@ -69,7 +69,7 @@ class WindowCovering(HomeAccessory):
The cover entity must support: set_cover_position.
"""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a WindowCovering accessory object."""
super().__init__(*args, category=CATEGORY_WINDOW_COVERING)
self.homekit_target = None
@ -108,7 +108,7 @@ class WindowCoveringBasic(HomeAccessory):
stop_cover (optional).
"""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a WindowCovering accessory object."""
super().__init__(*args, category=CATEGORY_WINDOW_COVERING)
features = self.hass.states.get(self.entity_id) \

View File

@ -26,7 +26,7 @@ class Light(HomeAccessory):
Currently supports: state, brightness, color temperature, rgb_color.
"""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a new Light accessory object."""
super().__init__(*args, category=CATEGORY_LIGHTBULB)
self._flag = {CHAR_ON: False, CHAR_BRIGHTNESS: False,

View File

@ -29,7 +29,7 @@ class Lock(HomeAccessory):
The lock entity must support: unlock and lock.
"""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a Lock accessory object."""
super().__init__(*args, category=CATEGORY_DOOR_LOCK)
self.flag_target_state = False

View File

@ -32,10 +32,10 @@ STATE_TO_SERVICE = {STATE_ALARM_ARMED_HOME: 'alarm_arm_home',
class SecuritySystem(HomeAccessory):
"""Generate an SecuritySystem accessory for an alarm control panel."""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a SecuritySystem accessory object."""
super().__init__(*args, category=CATEGORY_ALARM_SYSTEM)
self._alarm_code = config.get(ATTR_CODE)
self._alarm_code = self.config.get(ATTR_CODE)
self.flag_target_state = False
serv_alarm = self.add_preload_service(SERV_SECURITY_SYSTEM)

View File

@ -51,7 +51,7 @@ class TemperatureSensor(HomeAccessory):
Sensor entity must return temperature in °C, °F.
"""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a TemperatureSensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR)
serv_temp = self.add_preload_service(SERV_TEMPERATURE_SENSOR)
@ -74,7 +74,7 @@ class TemperatureSensor(HomeAccessory):
class HumiditySensor(HomeAccessory):
"""Generate a HumiditySensor accessory as humidity sensor."""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a HumiditySensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR)
serv_humidity = self.add_preload_service(SERV_HUMIDITY_SENSOR)
@ -94,7 +94,7 @@ class HumiditySensor(HomeAccessory):
class AirQualitySensor(HomeAccessory):
"""Generate a AirQualitySensor accessory as air quality sensor."""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a AirQualitySensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR)
@ -118,7 +118,7 @@ class AirQualitySensor(HomeAccessory):
class CarbonDioxideSensor(HomeAccessory):
"""Generate a CarbonDioxideSensor accessory as CO2 sensor."""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a CarbonDioxideSensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR)
@ -146,7 +146,7 @@ class CarbonDioxideSensor(HomeAccessory):
class LightSensor(HomeAccessory):
"""Generate a LightSensor accessory as light sensor."""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a LightSensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR)
@ -166,7 +166,7 @@ class LightSensor(HomeAccessory):
class BinarySensor(HomeAccessory):
"""Generate a BinarySensor accessory as binary sensor."""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a BinarySensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR)
device_class = self.hass.states.get(self.entity_id).attributes \

View File

@ -18,7 +18,7 @@ _LOGGER = logging.getLogger(__name__)
class Switch(HomeAccessory):
"""Generate a Switch accessory."""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a Switch accessory object to represent a remote."""
super().__init__(*args, category=CATEGORY_SWITCH)
self._domain = split_entity_id(self.entity_id)[0]

View File

@ -38,7 +38,7 @@ SUPPORT_TEMP_RANGE = SUPPORT_TARGET_TEMPERATURE_LOW | \
class Thermostat(HomeAccessory):
"""Generate a Thermostat accessory for a climate."""
def __init__(self, *args, config):
def __init__(self, *args):
"""Initialize a Thermostat accessory object."""
super().__init__(*args, category=CATEGORY_THERMOSTAT)
self._unit = TEMP_CELSIUS

View File

@ -5,7 +5,7 @@ import voluptuous as vol
from homeassistant.core import split_entity_id
from homeassistant.const import (
ATTR_CODE, TEMP_CELSIUS)
ATTR_CODE, CONF_NAME, TEMP_CELSIUS)
import homeassistant.helpers.config_validation as cv
import homeassistant.util.temperature as temp_util
from .const import HOMEKIT_NOTIFY_ID
@ -16,13 +16,18 @@ _LOGGER = logging.getLogger(__name__)
def validate_entity_config(values):
"""Validate config entry for CONF_ENTITY."""
entities = {}
for key, config in values.items():
entity = cv.entity_id(key)
for entity_id, config in values.items():
entity = cv.entity_id(entity_id)
params = {}
if not isinstance(config, dict):
raise vol.Invalid('The configuration for "{}" must be '
' an dictionary.'.format(entity))
for key in (CONF_NAME, ):
value = config.get(key, -1)
if value != -1:
params[key] = cv.string(value)
domain, _ = split_entity_id(entity)
if domain == 'alarm_control_panel':

View File

@ -56,9 +56,10 @@ async def test_debounce(hass):
async def test_home_accessory(hass):
"""Test HomeAccessory class."""
acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory', 2)
acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory', 2, None)
assert acc.hass == hass
assert acc.display_name == 'Home Accessory'
assert acc.aid == 2
assert acc.category == 1 # Category.OTHER
assert len(acc.services) == 1
serv = acc.services[0] # SERV_ACCESSORY_INFO
@ -75,7 +76,7 @@ async def test_home_accessory(hass):
hass.states.async_set('homekit.accessory', 'off')
await hass.async_block_till_done()
acc = HomeAccessory('hass', 'test_name', 'test_model.demo', 2)
acc = HomeAccessory('hass', 'test_name', 'test_model.demo', 2, None)
assert acc.display_name == 'test_name'
assert acc.aid == 2
assert len(acc.services) == 1

View File

@ -11,33 +11,42 @@ from homeassistant.components.climate import (
from homeassistant.components.homekit import get_accessory, TYPES
from homeassistant.const import (
ATTR_CODE, ATTR_DEVICE_CLASS, ATTR_SUPPORTED_FEATURES,
ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS, TEMP_FAHRENHEIT)
ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS, TEMP_FAHRENHEIT, CONF_NAME)
_LOGGER = logging.getLogger(__name__)
def test_get_accessory_invalid_aid(caplog):
"""Test with unsupported component."""
assert get_accessory(None, State('light.demo', 'on'),
None, config=None) is None
def test_not_supported(caplog):
"""Test if none is returned if entity isn't supported."""
# not supported entity
assert get_accessory(None, State('demo.demo', 'on'), 2, {}) is None
# invalid aid
assert get_accessory(None, State('light.demo', 'on'), None, None) is None
assert caplog.records[0].levelname == 'WARNING'
assert 'invalid aid' in caplog.records[0].msg
def test_not_supported():
"""Test if none is returned if entity isn't supported."""
assert get_accessory(None, State('demo.demo', 'on'), 2, config=None) \
is None
@pytest.mark.parametrize('config, name', [
({CONF_NAME: 'Customize Name'}, 'Customize Name'),
])
def test_customize_options(config, name):
"""Test with customized options."""
mock_type = Mock()
with patch.dict(TYPES, {'Light': mock_type}):
entity_state = State('light.demo', 'on')
get_accessory(None, entity_state, 2, config)
mock_type.assert_called_with(None, name, 'light.demo', 2, config)
@pytest.mark.parametrize('type_name, entity_id, state, attrs, config', [
('Light', 'light.test', 'on', {}, None),
('Lock', 'lock.test', 'locked', {}, None),
('Light', 'light.test', 'on', {}, {}),
('Lock', 'lock.test', 'locked', {}, {}),
('Thermostat', 'climate.test', 'auto', {}, None),
('Thermostat', 'climate.test', 'auto', {}, {}),
('Thermostat', 'climate.test', 'auto',
{ATTR_SUPPORTED_FEATURES: SUPPORT_TARGET_TEMPERATURE_LOW |
SUPPORT_TARGET_TEMPERATURE_HIGH}, None),
SUPPORT_TARGET_TEMPERATURE_HIGH}, {}),
('SecuritySystem', 'alarm_control_panel.test', 'armed', {},
{ATTR_CODE: '1234'}),
@ -51,7 +60,7 @@ def test_types(type_name, entity_id, state, attrs, config):
assert mock_type.called
if config:
assert mock_type.call_args[1]['config'] == config
assert mock_type.call_args[0][-1] == config
@pytest.mark.parametrize('type_name, entity_id, state, attrs', [
@ -68,7 +77,7 @@ def test_type_covers(type_name, entity_id, state, attrs):
mock_type = Mock()
with patch.dict(TYPES, {type_name: mock_type}):
entity_state = State(entity_id, state, attrs)
get_accessory(None, entity_state, 2, None)
get_accessory(None, entity_state, 2, {})
assert mock_type.called
@ -104,7 +113,7 @@ def test_type_sensors(type_name, entity_id, state, attrs):
mock_type = Mock()
with patch.dict(TYPES, {type_name: mock_type}):
entity_state = State(entity_id, state, attrs)
get_accessory(None, entity_state, 2, None)
get_accessory(None, entity_state, 2, {})
assert mock_type.called
@ -118,5 +127,5 @@ def test_type_switches(type_name, entity_id, state, attrs):
mock_type = Mock()
with patch.dict(TYPES, {type_name: mock_type}):
entity_state = State(entity_id, state, attrs)
get_accessory(None, entity_state, 2, None)
get_accessory(None, entity_state, 2, {})
assert mock_type.called

View File

@ -32,7 +32,7 @@ async def test_garage_door_open_close(hass, cls):
"""Test if accessory and HA are updated accordingly."""
entity_id = 'cover.garage_door'
acc = cls.garage(hass, 'Garage Door', entity_id, 2, config=None)
acc = cls.garage(hass, 'Garage Door', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
@ -87,7 +87,7 @@ async def test_window_set_cover_position(hass, cls):
"""Test if accessory and HA are updated accordingly."""
entity_id = 'cover.window'
acc = cls.window(hass, 'Cover', entity_id, 2, config=None)
acc = cls.window(hass, 'Cover', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
@ -135,7 +135,7 @@ async def test_window_open_close(hass, cls):
hass.states.async_set(entity_id, STATE_UNKNOWN,
{ATTR_SUPPORTED_FEATURES: 0})
acc = cls.window_basic(hass, 'Cover', entity_id, 2, config=None)
acc = cls.window_basic(hass, 'Cover', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
@ -198,7 +198,7 @@ async def test_window_open_close_stop(hass, cls):
hass.states.async_set(entity_id, STATE_UNKNOWN,
{ATTR_SUPPORTED_FEATURES: SUPPORT_STOP})
acc = cls.window_basic(hass, 'Cover', entity_id, 2, config=None)
acc = cls.window_basic(hass, 'Cover', entity_id, 2, None)
await hass.async_add_job(acc.run)
# Set from HomeKit

View File

@ -33,7 +33,7 @@ async def test_light_basic(hass, cls):
hass.states.async_set(entity_id, STATE_ON,
{ATTR_SUPPORTED_FEATURES: 0})
await hass.async_block_till_done()
acc = cls.light(hass, 'Light', entity_id, 2, config=None)
acc = cls.light(hass, 'Light', entity_id, 2, None)
assert acc.aid == 2
assert acc.category == 5 # Lightbulb
@ -81,7 +81,7 @@ async def test_light_brightness(hass, cls):
hass.states.async_set(entity_id, STATE_ON, {
ATTR_SUPPORTED_FEATURES: SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS: 255})
await hass.async_block_till_done()
acc = cls.light(hass, 'Light', entity_id, 2, config=None)
acc = cls.light(hass, 'Light', entity_id, 2, None)
assert acc.char_brightness.value == 0
@ -126,7 +126,7 @@ async def test_light_color_temperature(hass, cls):
ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR_TEMP,
ATTR_COLOR_TEMP: 190})
await hass.async_block_till_done()
acc = cls.light(hass, 'Light', entity_id, 2, config=None)
acc = cls.light(hass, 'Light', entity_id, 2, None)
assert acc.char_color_temperature.value == 153
@ -153,7 +153,7 @@ async def test_light_rgb_color(hass, cls):
ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR,
ATTR_HS_COLOR: (260, 90)})
await hass.async_block_till_done()
acc = cls.light(hass, 'Light', entity_id, 2, config=None)
acc = cls.light(hass, 'Light', entity_id, 2, None)
assert acc.char_hue.value == 0
assert acc.char_saturation.value == 75

View File

@ -11,7 +11,7 @@ async def test_lock_unlock(hass):
"""Test if accessory and HA are updated accordingly."""
entity_id = 'lock.kitchen_door'
acc = Lock(hass, 'Lock', entity_id, 2, config=None)
acc = Lock(hass, 'Lock', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2

View File

@ -5,9 +5,9 @@ from homeassistant.components.alarm_control_panel import DOMAIN
from homeassistant.components.homekit.type_security_systems import (
SecuritySystem)
from homeassistant.const import (
ATTR_CODE, ATTR_ENTITY_ID, STATE_UNKNOWN,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED)
ATTR_CODE, ATTR_ENTITY_ID, STATE_UNKNOWN, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED,
STATE_ALARM_TRIGGERED)
from tests.common import async_mock_service
@ -18,7 +18,7 @@ async def test_switch_set_state(hass):
config = {ATTR_CODE: code}
entity_id = 'alarm_control_panel.test'
acc = SecuritySystem(hass, 'SecuritySystem', entity_id, 2, config=config)
acc = SecuritySystem(hass, 'SecuritySystem', entity_id, 2, config)
await hass.async_add_job(acc.run)
assert acc.aid == 2
@ -97,7 +97,7 @@ async def test_no_alarm_code(hass, config):
"""Test accessory if security_system doesn't require a alarm_code."""
entity_id = 'alarm_control_panel.test'
acc = SecuritySystem(hass, 'SecuritySystem', entity_id, 2, config=config)
acc = SecuritySystem(hass, 'SecuritySystem', entity_id, 2, config)
# Set from HomeKit
call_arm_home = async_mock_service(hass, DOMAIN, 'alarm_arm_home')

View File

@ -12,7 +12,7 @@ async def test_temperature(hass):
"""Test if accessory is updated after state change."""
entity_id = 'sensor.temperature'
acc = TemperatureSensor(hass, 'Temperature', entity_id, 2, config=None)
acc = TemperatureSensor(hass, 'Temperature', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
@ -42,7 +42,7 @@ async def test_humidity(hass):
"""Test if accessory is updated after state change."""
entity_id = 'sensor.humidity'
acc = HumiditySensor(hass, 'Humidity', entity_id, 2, config=None)
acc = HumiditySensor(hass, 'Humidity', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
@ -63,7 +63,7 @@ async def test_air_quality(hass):
"""Test if accessory is updated after state change."""
entity_id = 'sensor.air_quality'
acc = AirQualitySensor(hass, 'Air Quality', entity_id, 2, config=None)
acc = AirQualitySensor(hass, 'Air Quality', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
@ -92,7 +92,7 @@ async def test_co2(hass):
"""Test if accessory is updated after state change."""
entity_id = 'sensor.co2'
acc = CarbonDioxideSensor(hass, 'CO2', entity_id, 2, config=None)
acc = CarbonDioxideSensor(hass, 'CO2', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
@ -125,7 +125,7 @@ async def test_light(hass):
"""Test if accessory is updated after state change."""
entity_id = 'sensor.light'
acc = LightSensor(hass, 'Light', entity_id, 2, config=None)
acc = LightSensor(hass, 'Light', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
@ -150,7 +150,7 @@ async def test_binary(hass):
{ATTR_DEVICE_CLASS: 'opening'})
await hass.async_block_till_done()
acc = BinarySensor(hass, 'Window Opening', entity_id, 2, config=None)
acc = BinarySensor(hass, 'Window Opening', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
@ -192,6 +192,6 @@ async def test_binary_device_classes(hass):
{ATTR_DEVICE_CLASS: device_class})
await hass.async_block_till_done()
acc = BinarySensor(hass, 'Binary Sensor', entity_id, 2, config=None)
acc = BinarySensor(hass, 'Binary Sensor', entity_id, 2, None)
assert acc.get_service(service).display_name == service
assert acc.char_detected.display_name == char

View File

@ -14,7 +14,7 @@ async def test_switch_set_state(hass, entity_id):
"""Test if accessory and HA are updated accordingly."""
domain = split_entity_id(entity_id)[0]
acc = Switch(hass, 'Switch', entity_id, 2, config=None)
acc = Switch(hass, 'Switch', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2

View File

@ -33,7 +33,7 @@ async def test_default_thermostat(hass, cls):
hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 0})
await hass.async_block_till_done()
acc = cls.thermostat(hass, 'Climate', entity_id, 2, config=None)
acc = cls.thermostat(hass, 'Climate', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.aid == 2
@ -173,7 +173,7 @@ async def test_auto_thermostat(hass, cls):
# support_auto = True
hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6})
await hass.async_block_till_done()
acc = cls.thermostat(hass, 'Climate', entity_id, 2, config=None)
acc = cls.thermostat(hass, 'Climate', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.char_cooling_thresh_temp.value == 23.0
@ -252,7 +252,7 @@ async def test_power_state(hass, cls):
ATTR_TEMPERATURE: 23.0,
ATTR_CURRENT_TEMPERATURE: 18.0})
await hass.async_block_till_done()
acc = cls.thermostat(hass, 'Climate', entity_id, 2, config=None)
acc = cls.thermostat(hass, 'Climate', entity_id, 2, None)
await hass.async_add_job(acc.run)
assert acc.support_power_state is True
@ -304,7 +304,7 @@ async def test_thermostat_fahrenheit(hass, cls):
# support_auto = True
hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6})
await hass.async_block_till_done()
acc = cls.thermostat(hass, 'Climate', entity_id, 2, config=None)
acc = cls.thermostat(hass, 'Climate', entity_id, 2, None)
await hass.async_add_job(acc.run)
hass.states.async_set(entity_id, STATE_AUTO,

View File

@ -12,7 +12,7 @@ from homeassistant.components.homekit.util import validate_entity_config \
from homeassistant.components.persistent_notification import (
DOMAIN, ATTR_NOTIFICATION_ID)
from homeassistant.const import (
ATTR_CODE, STATE_UNKNOWN, TEMP_CELSIUS, TEMP_FAHRENHEIT)
ATTR_CODE, STATE_UNKNOWN, TEMP_CELSIUS, TEMP_FAHRENHEIT, CONF_NAME)
from tests.common import async_mock_service
@ -21,13 +21,15 @@ def test_validate_entity_config():
"""Test validate entities."""
configs = [{'invalid_entity_id': {}}, {'demo.test': 1},
{'demo.test': 'test'}, {'demo.test': [1, 2]},
{'demo.test': None}]
{'demo.test': None}, {'demo.test': {CONF_NAME: None}}]
for conf in configs:
with pytest.raises(vol.Invalid):
vec(conf)
assert vec({}) == {}
assert vec({'demo.test': {CONF_NAME: 'Name'}}) == \
{'demo.test': {CONF_NAME: 'Name'}}
assert vec({'alarm_control_panel.demo': {ATTR_CODE: '1234'}}) == \
{'alarm_control_panel.demo': {ATTR_CODE: '1234'}}