Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions homeassistant/components/homekit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,19 @@
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__)
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -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):
Expand Down
12 changes: 7 additions & 5 deletions homeassistant/components/homekit/accessories.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
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)

Expand Down Expand Up @@ -64,14 +64,16 @@ def wrapper(*args):
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

Expand Down
6 changes: 3 additions & 3 deletions homeassistant/components/homekit/type_covers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) \
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/homekit/type_lights.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/homekit/type_locks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/homekit/type_security_systems.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@
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)
Expand Down
12 changes: 6 additions & 6 deletions homeassistant/components/homekit/type_sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -74,7 +74,7 @@ def update_state(self, new_state):
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)
Expand All @@ -94,7 +94,7 @@ def update_state(self, new_state):
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)

Expand All @@ -118,7 +118,7 @@ def update_state(self, new_state):
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)

Expand Down Expand Up @@ -146,7 +146,7 @@ def update_state(self, new_state):
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)

Expand All @@ -166,7 +166,7 @@ def update_state(self, new_state):
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 \
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/homekit/type_switches.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
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]
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/homekit/type_thermostats.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
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
Expand Down
11 changes: 8 additions & 3 deletions homeassistant/components/homekit/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

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
Expand All @@ -16,13 +16,18 @@
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':
Expand Down
5 changes: 3 additions & 2 deletions tests/components/homekit/test_accessories.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ def demo_func(*args):

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
Expand All @@ -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
Expand Down
43 changes: 26 additions & 17 deletions tests/components/homekit/test_get_accessories.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,42 @@
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'}),
Expand All @@ -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', [
Expand All @@ -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


Expand Down Expand Up @@ -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


Expand All @@ -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
8 changes: 4 additions & 4 deletions tests/components/homekit/test_type_covers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading