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 ( from homeassistant.components.cover import (
SUPPORT_CLOSE, SUPPORT_OPEN, SUPPORT_SET_POSITION) SUPPORT_CLOSE, SUPPORT_OPEN, SUPPORT_SET_POSITION)
from homeassistant.const import ( from homeassistant.const import (
ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, ATTR_DEVICE_CLASS, ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT,
ATTR_DEVICE_CLASS, CONF_IP_ADDRESS, CONF_PORT, TEMP_CELSIUS, CONF_IP_ADDRESS, CONF_NAME, CONF_PORT, TEMP_CELSIUS, TEMP_FAHRENHEIT,
TEMP_FAHRENHEIT, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_TEMPERATURE) DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_TEMPERATURE)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entityfilter import FILTER_SCHEMA from homeassistant.helpers.entityfilter import FILTER_SCHEMA
from homeassistant.util import get_local_ip from homeassistant.util import get_local_ip
from homeassistant.util.decorator import Registry from homeassistant.util.decorator import Registry
from .const import ( from .const import (
DOMAIN, HOMEKIT_FILE, CONF_AUTO_START, CONF_ENTITY_CONFIG, CONF_FILTER, CONF_AUTO_START, CONF_ENTITY_CONFIG, CONF_FILTER, DEFAULT_PORT,
DEFAULT_PORT, DEFAULT_AUTO_START, SERVICE_HOMEKIT_START, DEFAULT_AUTO_START, DOMAIN, HOMEKIT_FILE, SERVICE_HOMEKIT_START,
DEVICE_CLASS_CO2, DEVICE_CLASS_PM25) DEVICE_CLASS_CO2, DEVICE_CLASS_PM25)
from .util import ( from .util import show_setup_message, validate_entity_config
validate_entity_config, show_setup_message)
TYPES = Registry() TYPES = Registry()
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -93,7 +92,7 @@ def get_accessory(hass, state, aid, config):
return None return None
a_type = None a_type = None
config = config or {} name = config.get(CONF_NAME, state.name)
if state.domain == 'alarm_control_panel': if state.domain == 'alarm_control_panel':
a_type = 'SecuritySystem' a_type = 'SecuritySystem'
@ -147,7 +146,7 @@ def get_accessory(hass, state, aid, config):
return None return None
_LOGGER.debug('Add "%s" as "%s"', state.entity_id, a_type) _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): 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 homeassistant.util import dt as dt_util
from .const import ( from .const import (
DEBOUNCE_TIMEOUT, BRIDGE_MODEL, BRIDGE_NAME, BRIDGE_MODEL, BRIDGE_NAME, BRIDGE_SERIAL_NUMBER,
BRIDGE_SERIAL_NUMBER, MANUFACTURER) DEBOUNCE_TIMEOUT, MANUFACTURER)
from .util import ( from .util import (
show_setup_message, dismiss_setup_message) show_setup_message, dismiss_setup_message)
@ -64,14 +64,16 @@ def debounce(func):
class HomeAccessory(Accessory): class HomeAccessory(Accessory):
"""Adapter class for 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.""" """Initialize a Accessory object."""
super().__init__(name, aid=aid) 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( self.set_info_service(
firmware_revision=__version__, manufacturer=MANUFACTURER, firmware_revision=__version__, manufacturer=MANUFACTURER,
model=domain, serial_number=entity_id) model=model, serial_number=entity_id)
self.category = category self.category = category
self.config = config
self.entity_id = entity_id self.entity_id = entity_id
self.hass = hass self.hass = hass

View File

@ -28,7 +28,7 @@ class GarageDoorOpener(HomeAccessory):
and support no more than open, close, and stop. and support no more than open, close, and stop.
""" """
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a GarageDoorOpener accessory object.""" """Initialize a GarageDoorOpener accessory object."""
super().__init__(*args, category=CATEGORY_GARAGE_DOOR_OPENER) super().__init__(*args, category=CATEGORY_GARAGE_DOOR_OPENER)
self.flag_target_state = False self.flag_target_state = False
@ -69,7 +69,7 @@ class WindowCovering(HomeAccessory):
The cover entity must support: set_cover_position. The cover entity must support: set_cover_position.
""" """
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a WindowCovering accessory object.""" """Initialize a WindowCovering accessory object."""
super().__init__(*args, category=CATEGORY_WINDOW_COVERING) super().__init__(*args, category=CATEGORY_WINDOW_COVERING)
self.homekit_target = None self.homekit_target = None
@ -108,7 +108,7 @@ class WindowCoveringBasic(HomeAccessory):
stop_cover (optional). stop_cover (optional).
""" """
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a WindowCovering accessory object.""" """Initialize a WindowCovering accessory object."""
super().__init__(*args, category=CATEGORY_WINDOW_COVERING) super().__init__(*args, category=CATEGORY_WINDOW_COVERING)
features = self.hass.states.get(self.entity_id) \ 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. Currently supports: state, brightness, color temperature, rgb_color.
""" """
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a new Light accessory object.""" """Initialize a new Light accessory object."""
super().__init__(*args, category=CATEGORY_LIGHTBULB) super().__init__(*args, category=CATEGORY_LIGHTBULB)
self._flag = {CHAR_ON: False, CHAR_BRIGHTNESS: False, 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. The lock entity must support: unlock and lock.
""" """
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a Lock accessory object.""" """Initialize a Lock accessory object."""
super().__init__(*args, category=CATEGORY_DOOR_LOCK) super().__init__(*args, category=CATEGORY_DOOR_LOCK)
self.flag_target_state = False self.flag_target_state = False

View File

@ -32,10 +32,10 @@ STATE_TO_SERVICE = {STATE_ALARM_ARMED_HOME: 'alarm_arm_home',
class SecuritySystem(HomeAccessory): class SecuritySystem(HomeAccessory):
"""Generate an SecuritySystem accessory for an alarm control panel.""" """Generate an SecuritySystem accessory for an alarm control panel."""
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a SecuritySystem accessory object.""" """Initialize a SecuritySystem accessory object."""
super().__init__(*args, category=CATEGORY_ALARM_SYSTEM) 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 self.flag_target_state = False
serv_alarm = self.add_preload_service(SERV_SECURITY_SYSTEM) 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. Sensor entity must return temperature in °C, °F.
""" """
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a TemperatureSensor accessory object.""" """Initialize a TemperatureSensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR) super().__init__(*args, category=CATEGORY_SENSOR)
serv_temp = self.add_preload_service(SERV_TEMPERATURE_SENSOR) serv_temp = self.add_preload_service(SERV_TEMPERATURE_SENSOR)
@ -74,7 +74,7 @@ class TemperatureSensor(HomeAccessory):
class HumiditySensor(HomeAccessory): class HumiditySensor(HomeAccessory):
"""Generate a HumiditySensor accessory as humidity sensor.""" """Generate a HumiditySensor accessory as humidity sensor."""
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a HumiditySensor accessory object.""" """Initialize a HumiditySensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR) super().__init__(*args, category=CATEGORY_SENSOR)
serv_humidity = self.add_preload_service(SERV_HUMIDITY_SENSOR) serv_humidity = self.add_preload_service(SERV_HUMIDITY_SENSOR)
@ -94,7 +94,7 @@ class HumiditySensor(HomeAccessory):
class AirQualitySensor(HomeAccessory): class AirQualitySensor(HomeAccessory):
"""Generate a AirQualitySensor accessory as air quality sensor.""" """Generate a AirQualitySensor accessory as air quality sensor."""
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a AirQualitySensor accessory object.""" """Initialize a AirQualitySensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR) super().__init__(*args, category=CATEGORY_SENSOR)
@ -118,7 +118,7 @@ class AirQualitySensor(HomeAccessory):
class CarbonDioxideSensor(HomeAccessory): class CarbonDioxideSensor(HomeAccessory):
"""Generate a CarbonDioxideSensor accessory as CO2 sensor.""" """Generate a CarbonDioxideSensor accessory as CO2 sensor."""
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a CarbonDioxideSensor accessory object.""" """Initialize a CarbonDioxideSensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR) super().__init__(*args, category=CATEGORY_SENSOR)
@ -146,7 +146,7 @@ class CarbonDioxideSensor(HomeAccessory):
class LightSensor(HomeAccessory): class LightSensor(HomeAccessory):
"""Generate a LightSensor accessory as light sensor.""" """Generate a LightSensor accessory as light sensor."""
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a LightSensor accessory object.""" """Initialize a LightSensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR) super().__init__(*args, category=CATEGORY_SENSOR)
@ -166,7 +166,7 @@ class LightSensor(HomeAccessory):
class BinarySensor(HomeAccessory): class BinarySensor(HomeAccessory):
"""Generate a BinarySensor accessory as binary sensor.""" """Generate a BinarySensor accessory as binary sensor."""
def __init__(self, *args, config): def __init__(self, *args):
"""Initialize a BinarySensor accessory object.""" """Initialize a BinarySensor accessory object."""
super().__init__(*args, category=CATEGORY_SENSOR) super().__init__(*args, category=CATEGORY_SENSOR)
device_class = self.hass.states.get(self.entity_id).attributes \ device_class = self.hass.states.get(self.entity_id).attributes \

View File

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

View File

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

View File

@ -56,9 +56,10 @@ async def test_debounce(hass):
async def test_home_accessory(hass): async def test_home_accessory(hass):
"""Test HomeAccessory class.""" """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.hass == hass
assert acc.display_name == 'Home Accessory' assert acc.display_name == 'Home Accessory'
assert acc.aid == 2
assert acc.category == 1 # Category.OTHER assert acc.category == 1 # Category.OTHER
assert len(acc.services) == 1 assert len(acc.services) == 1
serv = acc.services[0] # SERV_ACCESSORY_INFO serv = acc.services[0] # SERV_ACCESSORY_INFO
@ -75,7 +76,7 @@ async def test_home_accessory(hass):
hass.states.async_set('homekit.accessory', 'off') hass.states.async_set('homekit.accessory', 'off')
await hass.async_block_till_done() 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.display_name == 'test_name'
assert acc.aid == 2 assert acc.aid == 2
assert len(acc.services) == 1 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.components.homekit import get_accessory, TYPES
from homeassistant.const import ( from homeassistant.const import (
ATTR_CODE, ATTR_DEVICE_CLASS, ATTR_SUPPORTED_FEATURES, 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__) _LOGGER = logging.getLogger(__name__)
def test_get_accessory_invalid_aid(caplog): def test_not_supported(caplog):
"""Test with unsupported component.""" """Test if none is returned if entity isn't supported."""
assert get_accessory(None, State('light.demo', 'on'), # not supported entity
None, config=None) is None 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 caplog.records[0].levelname == 'WARNING'
assert 'invalid aid' in caplog.records[0].msg assert 'invalid aid' in caplog.records[0].msg
def test_not_supported(): @pytest.mark.parametrize('config, name', [
"""Test if none is returned if entity isn't supported.""" ({CONF_NAME: 'Customize Name'}, 'Customize Name'),
assert get_accessory(None, State('demo.demo', 'on'), 2, config=None) \ ])
is None 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', [ @pytest.mark.parametrize('type_name, entity_id, state, attrs, config', [
('Light', 'light.test', 'on', {}, None), ('Light', 'light.test', 'on', {}, {}),
('Lock', 'lock.test', 'locked', {}, None), ('Lock', 'lock.test', 'locked', {}, {}),
('Thermostat', 'climate.test', 'auto', {}, None), ('Thermostat', 'climate.test', 'auto', {}, {}),
('Thermostat', 'climate.test', 'auto', ('Thermostat', 'climate.test', 'auto',
{ATTR_SUPPORTED_FEATURES: SUPPORT_TARGET_TEMPERATURE_LOW | {ATTR_SUPPORTED_FEATURES: SUPPORT_TARGET_TEMPERATURE_LOW |
SUPPORT_TARGET_TEMPERATURE_HIGH}, None), SUPPORT_TARGET_TEMPERATURE_HIGH}, {}),
('SecuritySystem', 'alarm_control_panel.test', 'armed', {}, ('SecuritySystem', 'alarm_control_panel.test', 'armed', {},
{ATTR_CODE: '1234'}), {ATTR_CODE: '1234'}),
@ -51,7 +60,7 @@ def test_types(type_name, entity_id, state, attrs, config):
assert mock_type.called assert mock_type.called
if config: 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', [ @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() mock_type = Mock()
with patch.dict(TYPES, {type_name: mock_type}): with patch.dict(TYPES, {type_name: mock_type}):
entity_state = State(entity_id, state, attrs) entity_state = State(entity_id, state, attrs)
get_accessory(None, entity_state, 2, None) get_accessory(None, entity_state, 2, {})
assert mock_type.called assert mock_type.called
@ -104,7 +113,7 @@ def test_type_sensors(type_name, entity_id, state, attrs):
mock_type = Mock() mock_type = Mock()
with patch.dict(TYPES, {type_name: mock_type}): with patch.dict(TYPES, {type_name: mock_type}):
entity_state = State(entity_id, state, attrs) entity_state = State(entity_id, state, attrs)
get_accessory(None, entity_state, 2, None) get_accessory(None, entity_state, 2, {})
assert mock_type.called assert mock_type.called
@ -118,5 +127,5 @@ def test_type_switches(type_name, entity_id, state, attrs):
mock_type = Mock() mock_type = Mock()
with patch.dict(TYPES, {type_name: mock_type}): with patch.dict(TYPES, {type_name: mock_type}):
entity_state = State(entity_id, state, attrs) entity_state = State(entity_id, state, attrs)
get_accessory(None, entity_state, 2, None) get_accessory(None, entity_state, 2, {})
assert mock_type.called 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.""" """Test if accessory and HA are updated accordingly."""
entity_id = 'cover.garage_door' 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 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.""" """Test if accessory and HA are updated accordingly."""
entity_id = 'cover.window' 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 assert acc.aid == 2
@ -135,7 +135,7 @@ async def test_window_open_close(hass, cls):
hass.states.async_set(entity_id, STATE_UNKNOWN, hass.states.async_set(entity_id, STATE_UNKNOWN,
{ATTR_SUPPORTED_FEATURES: 0}) {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) await hass.async_add_job(acc.run)
assert acc.aid == 2 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, hass.states.async_set(entity_id, STATE_UNKNOWN,
{ATTR_SUPPORTED_FEATURES: SUPPORT_STOP}) {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) await hass.async_add_job(acc.run)
# Set from HomeKit # Set from HomeKit

View File

@ -33,7 +33,7 @@ async def test_light_basic(hass, cls):
hass.states.async_set(entity_id, STATE_ON, hass.states.async_set(entity_id, STATE_ON,
{ATTR_SUPPORTED_FEATURES: 0}) {ATTR_SUPPORTED_FEATURES: 0})
await hass.async_block_till_done() 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.aid == 2
assert acc.category == 5 # Lightbulb assert acc.category == 5 # Lightbulb
@ -81,7 +81,7 @@ async def test_light_brightness(hass, cls):
hass.states.async_set(entity_id, STATE_ON, { hass.states.async_set(entity_id, STATE_ON, {
ATTR_SUPPORTED_FEATURES: SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS: 255}) ATTR_SUPPORTED_FEATURES: SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS: 255})
await hass.async_block_till_done() 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 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_SUPPORTED_FEATURES: SUPPORT_COLOR_TEMP,
ATTR_COLOR_TEMP: 190}) ATTR_COLOR_TEMP: 190})
await hass.async_block_till_done() 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 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_SUPPORTED_FEATURES: SUPPORT_COLOR,
ATTR_HS_COLOR: (260, 90)}) ATTR_HS_COLOR: (260, 90)})
await hass.async_block_till_done() 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_hue.value == 0
assert acc.char_saturation.value == 75 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.""" """Test if accessory and HA are updated accordingly."""
entity_id = 'lock.kitchen_door' 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 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 ( from homeassistant.components.homekit.type_security_systems import (
SecuritySystem) SecuritySystem)
from homeassistant.const import ( from homeassistant.const import (
ATTR_CODE, ATTR_ENTITY_ID, STATE_UNKNOWN, ATTR_CODE, ATTR_ENTITY_ID, STATE_UNKNOWN, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED,
STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED) STATE_ALARM_TRIGGERED)
from tests.common import async_mock_service from tests.common import async_mock_service
@ -18,7 +18,7 @@ async def test_switch_set_state(hass):
config = {ATTR_CODE: code} config = {ATTR_CODE: code}
entity_id = 'alarm_control_panel.test' 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 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.""" """Test accessory if security_system doesn't require a alarm_code."""
entity_id = 'alarm_control_panel.test' 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 # Set from HomeKit
call_arm_home = async_mock_service(hass, DOMAIN, 'alarm_arm_home') 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.""" """Test if accessory is updated after state change."""
entity_id = 'sensor.temperature' 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 assert acc.aid == 2
@ -42,7 +42,7 @@ async def test_humidity(hass):
"""Test if accessory is updated after state change.""" """Test if accessory is updated after state change."""
entity_id = 'sensor.humidity' 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 assert acc.aid == 2
@ -63,7 +63,7 @@ async def test_air_quality(hass):
"""Test if accessory is updated after state change.""" """Test if accessory is updated after state change."""
entity_id = 'sensor.air_quality' 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 assert acc.aid == 2
@ -92,7 +92,7 @@ async def test_co2(hass):
"""Test if accessory is updated after state change.""" """Test if accessory is updated after state change."""
entity_id = 'sensor.co2' 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 assert acc.aid == 2
@ -125,7 +125,7 @@ async def test_light(hass):
"""Test if accessory is updated after state change.""" """Test if accessory is updated after state change."""
entity_id = 'sensor.light' 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 assert acc.aid == 2
@ -150,7 +150,7 @@ async def test_binary(hass):
{ATTR_DEVICE_CLASS: 'opening'}) {ATTR_DEVICE_CLASS: 'opening'})
await hass.async_block_till_done() 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 assert acc.aid == 2
@ -192,6 +192,6 @@ async def test_binary_device_classes(hass):
{ATTR_DEVICE_CLASS: device_class}) {ATTR_DEVICE_CLASS: device_class})
await hass.async_block_till_done() 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.get_service(service).display_name == service
assert acc.char_detected.display_name == char 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.""" """Test if accessory and HA are updated accordingly."""
domain = split_entity_id(entity_id)[0] 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 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}) hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 0})
await hass.async_block_till_done() 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) await hass.async_add_job(acc.run)
assert acc.aid == 2 assert acc.aid == 2
@ -173,7 +173,7 @@ async def test_auto_thermostat(hass, cls):
# support_auto = True # support_auto = True
hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6}) hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6})
await hass.async_block_till_done() 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) await hass.async_add_job(acc.run)
assert acc.char_cooling_thresh_temp.value == 23.0 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_TEMPERATURE: 23.0,
ATTR_CURRENT_TEMPERATURE: 18.0}) ATTR_CURRENT_TEMPERATURE: 18.0})
await hass.async_block_till_done() 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) await hass.async_add_job(acc.run)
assert acc.support_power_state is True assert acc.support_power_state is True
@ -304,7 +304,7 @@ async def test_thermostat_fahrenheit(hass, cls):
# support_auto = True # support_auto = True
hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6}) hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6})
await hass.async_block_till_done() 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) await hass.async_add_job(acc.run)
hass.states.async_set(entity_id, STATE_AUTO, 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 ( from homeassistant.components.persistent_notification import (
DOMAIN, ATTR_NOTIFICATION_ID) DOMAIN, ATTR_NOTIFICATION_ID)
from homeassistant.const import ( 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 from tests.common import async_mock_service
@ -21,13 +21,15 @@ def test_validate_entity_config():
"""Test validate entities.""" """Test validate entities."""
configs = [{'invalid_entity_id': {}}, {'demo.test': 1}, configs = [{'invalid_entity_id': {}}, {'demo.test': 1},
{'demo.test': 'test'}, {'demo.test': [1, 2]}, {'demo.test': 'test'}, {'demo.test': [1, 2]},
{'demo.test': None}] {'demo.test': None}, {'demo.test': {CONF_NAME: None}}]
for conf in configs: for conf in configs:
with pytest.raises(vol.Invalid): with pytest.raises(vol.Invalid):
vec(conf) vec(conf)
assert vec({}) == {} assert vec({}) == {}
assert vec({'demo.test': {CONF_NAME: 'Name'}}) == \
{'demo.test': {CONF_NAME: 'Name'}}
assert vec({'alarm_control_panel.demo': {ATTR_CODE: '1234'}}) == \ assert vec({'alarm_control_panel.demo': {ATTR_CODE: '1234'}}) == \
{'alarm_control_panel.demo': {ATTR_CODE: '1234'}} {'alarm_control_panel.demo': {ATTR_CODE: '1234'}}