diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index 22c74faf5f0..02d21889f6b 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -8,11 +8,9 @@ from zlib import adler32 import voluptuous as vol -from homeassistant.components.climate import ( - SUPPORT_TARGET_TEMPERATURE_HIGH, SUPPORT_TARGET_TEMPERATURE_LOW) from homeassistant.components.cover import SUPPORT_SET_POSITION from homeassistant.const import ( - ATTR_CODE, ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, + ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, CONF_PORT, TEMP_CELSIUS, TEMP_FAHRENHEIT, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP) import homeassistant.helpers.config_validation as cv @@ -79,63 +77,46 @@ def get_accessory(hass, state, aid, config): state.entity_id) return None - if state.domain == 'sensor': - unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) - if unit == TEMP_CELSIUS or unit == TEMP_FAHRENHEIT: - _LOGGER.debug('Add "%s" as "%s"', - state.entity_id, 'TemperatureSensor') - return TYPES['TemperatureSensor'](hass, state.entity_id, - state.name, aid=aid) - elif unit == '%': - _LOGGER.debug('Add "%s" as %s"', - state.entity_id, 'HumiditySensor') - return TYPES['HumiditySensor'](hass, state.entity_id, state.name, - aid=aid) + a_type = None + config = config or {} + + if state.domain == 'alarm_control_panel': + a_type = 'SecuritySystem' elif state.domain == 'binary_sensor' or state.domain == 'device_tracker': - _LOGGER.debug('Add "%s" as "%s"', state.entity_id, 'BinarySensor') - return TYPES['BinarySensor'](hass, state.entity_id, - state.name, aid=aid) + a_type = 'BinarySensor' + + elif state.domain == 'climate': + a_type = 'Thermostat' elif state.domain == 'cover': # Only add covers that support set_cover_position features = state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) if features & SUPPORT_SET_POSITION: - _LOGGER.debug('Add "%s" as "%s"', - state.entity_id, 'WindowCovering') - return TYPES['WindowCovering'](hass, state.entity_id, state.name, - aid=aid) - - elif state.domain == 'alarm_control_panel': - _LOGGER.debug('Add "%s" as "%s"', state.entity_id, 'SecuritySystem') - return TYPES['SecuritySystem'](hass, state.entity_id, state.name, - alarm_code=config.get(ATTR_CODE), - aid=aid) - - elif state.domain == 'climate': - features = state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) - support_temp_range = SUPPORT_TARGET_TEMPERATURE_LOW | \ - SUPPORT_TARGET_TEMPERATURE_HIGH - # Check if climate device supports auto mode - support_auto = bool(features & support_temp_range) - - _LOGGER.debug('Add "%s" as "%s"', state.entity_id, 'Thermostat') - return TYPES['Thermostat'](hass, state.entity_id, - state.name, support_auto, aid=aid) + a_type = 'WindowCovering' elif state.domain == 'light': - _LOGGER.debug('Add "%s" as "%s"', state.entity_id, 'Light') - return TYPES['Light'](hass, state.entity_id, state.name, aid=aid) + a_type = 'Light' elif state.domain == 'lock': - return TYPES['Lock'](hass, state.entity_id, state.name, aid=aid) + a_type = 'Lock' + + elif state.domain == 'sensor': + unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) + if unit == TEMP_CELSIUS or unit == TEMP_FAHRENHEIT: + a_type = 'TemperatureSensor' + elif unit == '%': + a_type = 'HumiditySensor' elif state.domain == 'switch' or state.domain == 'remote' \ or state.domain == 'input_boolean' or state.domain == 'script': - _LOGGER.debug('Add "%s" as "%s"', state.entity_id, 'Switch') - return TYPES['Switch'](hass, state.entity_id, state.name, aid=aid) + a_type = 'Switch' - return None + if a_type is None: + 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) def generate_aid(entity_id): @@ -151,7 +132,7 @@ class HomeKit(): def __init__(self, hass, port, entity_filter, entity_config): """Initialize a HomeKit object.""" - self._hass = hass + self.hass = hass self._port = port self._filter = entity_filter self._config = entity_config @@ -164,11 +145,11 @@ class HomeKit(): """Setup bridge and accessory driver.""" from .accessories import HomeBridge, HomeDriver - self._hass.bus.async_listen_once( + self.hass.bus.async_listen_once( EVENT_HOMEASSISTANT_STOP, self.stop) - path = self._hass.config.path(HOMEKIT_FILE) - self.bridge = HomeBridge(self._hass) + path = self.hass.config.path(HOMEKIT_FILE) + self.bridge = HomeBridge(self.hass) self.driver = HomeDriver(self.bridge, self._port, get_local_ip(), path) def add_bridge_accessory(self, state): @@ -177,7 +158,7 @@ class HomeKit(): return aid = generate_aid(state.entity_id) conf = self._config.pop(state.entity_id, {}) - acc = get_accessory(self._hass, state, aid, conf) + acc = get_accessory(self.hass, state, aid, conf) if acc is not None: self.bridge.add_accessory(acc) @@ -192,12 +173,12 @@ class HomeKit(): type_covers, type_lights, type_locks, type_security_systems, type_sensors, type_switches, type_thermostats) - for state in self._hass.states.all(): + for state in self.hass.states.all(): self.add_bridge_accessory(state) self.bridge.set_broker(self.driver) if not self.bridge.paired: - show_setup_message(self.bridge, self._hass) + show_setup_message(self.hass, self.bridge) _LOGGER.debug('Driver start') self.driver.start() diff --git a/homeassistant/components/homekit/accessories.py b/homeassistant/components/homekit/accessories.py index ec2c49f5e43..d9b90a77d68 100644 --- a/homeassistant/components/homekit/accessories.py +++ b/homeassistant/components/homekit/accessories.py @@ -7,14 +7,14 @@ import logging from pyhap.accessory import Accessory, Bridge, Category from pyhap.accessory_driver import AccessoryDriver -from homeassistant.core import callback +from homeassistant.core import callback as ha_callback from homeassistant.helpers.event import ( async_track_state_change, track_point_in_utc_time) from homeassistant.util import dt as dt_util from .const import ( - DEBOUNCE_TIMEOUT, ACCESSORY_MODEL, ACCESSORY_NAME, BRIDGE_MODEL, - BRIDGE_NAME, MANUFACTURER, SERV_ACCESSORY_INFO, CHAR_MANUFACTURER, + DEBOUNCE_TIMEOUT, BRIDGE_MODEL, BRIDGE_NAME, MANUFACTURER, + SERV_ACCESSORY_INFO, CHAR_MANUFACTURER, CHAR_MODEL, CHAR_NAME, CHAR_SERIAL_NUMBER) from .util import ( show_setup_message, dismiss_setup_message) @@ -24,7 +24,7 @@ _LOGGER = logging.getLogger(__name__) def debounce(func): """Decorator function. Debounce callbacks form HomeKit.""" - @callback + @ha_callback def call_later_listener(*args): """Callback listener called from call_later.""" # pylint: disable=unsubscriptable-object @@ -72,6 +72,18 @@ def add_preload_service(acc, service, chars=None): return service +def setup_char(char_name, service, value=None, properties=None, callback=None): + """Helper function to return fully configured characteristic.""" + char = service.get_characteristic(char_name) + if value: + char.value = value + if properties: + char.override_properties(properties) + if callback: + char.setter_callback = callback + return char + + def set_accessory_info(acc, name, model, manufacturer=MANUFACTURER, serial_number='0000'): """Set the default accessory information.""" @@ -85,14 +97,13 @@ def set_accessory_info(acc, name, model, manufacturer=MANUFACTURER, class HomeAccessory(Accessory): """Adapter class for Accessory.""" - # pylint: disable=no-member - - def __init__(self, name=ACCESSORY_NAME, model=ACCESSORY_MODEL, - category='OTHER', **kwargs): + def __init__(self, hass, name, entity_id, aid, category): """Initialize a Accessory object.""" - super().__init__(name, **kwargs) - set_accessory_info(self, name, model) + super().__init__(name, aid=aid) + set_accessory_info(self, name, model=entity_id) self.category = getattr(Category, category, Category.OTHER) + self.entity_id = entity_id + self.hass = hass def _set_services(self): add_preload_service(self, SERV_ACCESSORY_INFO) @@ -100,19 +111,33 @@ class HomeAccessory(Accessory): def run(self): """Method called by accessory after driver is started.""" state = self.hass.states.get(self.entity_id) - self.update_state(new_state=state) + self.update_state_callback(new_state=state) async_track_state_change( - self.hass, self.entity_id, self.update_state) + self.hass, self.entity_id, self.update_state_callback) + + def update_state_callback(self, entity_id=None, old_state=None, + new_state=None): + """Callback from state change listener.""" + _LOGGER.debug('New_state: %s', new_state) + if new_state is None: + return + self.update_state(new_state) + + def update_state(self, new_state): + """Method called on state change to update HomeKit value. + + Overridden by accessory types. + """ + pass class HomeBridge(Bridge): """Adapter class for Bridge.""" - def __init__(self, hass, name=BRIDGE_NAME, - model=BRIDGE_MODEL, **kwargs): + def __init__(self, hass, name=BRIDGE_NAME): """Initialize a Bridge object.""" - super().__init__(name, **kwargs) - set_accessory_info(self, name, model) + super().__init__(name) + set_accessory_info(self, name, model=BRIDGE_MODEL) self.hass = hass def _set_services(self): @@ -130,7 +155,7 @@ class HomeBridge(Bridge): def remove_paired_client(self, client_uuid): """Override super function to show setup message if unpaired.""" super().remove_paired_client(client_uuid) - show_setup_message(self, self.hass) + show_setup_message(self.hass, self) class HomeDriver(AccessoryDriver): diff --git a/homeassistant/components/homekit/const.py b/homeassistant/components/homekit/const.py index e5a4c80a430..80f2fd039e6 100644 --- a/homeassistant/components/homekit/const.py +++ b/homeassistant/components/homekit/const.py @@ -18,8 +18,6 @@ DEFAULT_PORT = 51827 SERVICE_HOMEKIT_START = 'start' # #### STRING CONSTANTS #### -ACCESSORY_MODEL = 'homekit.accessory' -ACCESSORY_NAME = 'Home Accessory' BRIDGE_MODEL = 'homekit.bridge' BRIDGE_NAME = 'Home Assistant' MANUFACTURER = 'HomeAssistant' diff --git a/homeassistant/components/homekit/type_covers.py b/homeassistant/components/homekit/type_covers.py index 781f52941fc..7c7ab3e3683 100644 --- a/homeassistant/components/homekit/type_covers.py +++ b/homeassistant/components/homekit/type_covers.py @@ -4,12 +4,11 @@ import logging from homeassistant.components.cover import ATTR_CURRENT_POSITION from . import TYPES -from .accessories import HomeAccessory, add_preload_service +from .accessories import HomeAccessory, add_preload_service, setup_char from .const import ( CATEGORY_WINDOW_COVERING, SERV_WINDOW_COVERING, CHAR_CURRENT_POSITION, CHAR_TARGET_POSITION, CHAR_POSITION_STATE) - _LOGGER = logging.getLogger(__name__) @@ -20,29 +19,20 @@ class WindowCovering(HomeAccessory): The cover entity must support: set_cover_position. """ - def __init__(self, hass, entity_id, display_name, **kwargs): + def __init__(self, *args, config): """Initialize a WindowCovering accessory object.""" - super().__init__(display_name, entity_id, - CATEGORY_WINDOW_COVERING, **kwargs) - - self.hass = hass - self.entity_id = entity_id - + super().__init__(*args, category=CATEGORY_WINDOW_COVERING) self.current_position = None self.homekit_target = None serv_cover = add_preload_service(self, SERV_WINDOW_COVERING) - self.char_current_position = serv_cover. \ - get_characteristic(CHAR_CURRENT_POSITION) - self.char_target_position = serv_cover. \ - get_characteristic(CHAR_TARGET_POSITION) - self.char_position_state = serv_cover. \ - get_characteristic(CHAR_POSITION_STATE) - self.char_current_position.value = 0 - self.char_target_position.value = 0 - self.char_position_state.value = 0 - - self.char_target_position.setter_callback = self.move_cover + self.char_current_position = setup_char( + CHAR_CURRENT_POSITION, serv_cover, value=0) + self.char_target_position = setup_char( + CHAR_TARGET_POSITION, serv_cover, value=0, + callback=self.move_cover) + self.char_position_state = setup_char( + CHAR_POSITION_STATE, serv_cover, value=0) def move_cover(self, value): """Move cover to value if call came from HomeKit.""" @@ -56,11 +46,8 @@ class WindowCovering(HomeAccessory): self.hass.components.cover.set_cover_position( value, self.entity_id) - def update_state(self, entity_id=None, old_state=None, new_state=None): + def update_state(self, new_state): """Update cover position after state changed.""" - if new_state is None: - return - current_position = new_state.attributes.get(ATTR_CURRENT_POSITION) if isinstance(current_position, int): self.current_position = current_position diff --git a/homeassistant/components/homekit/type_lights.py b/homeassistant/components/homekit/type_lights.py index 4fbfb995859..9a7bce76fba 100644 --- a/homeassistant/components/homekit/type_lights.py +++ b/homeassistant/components/homekit/type_lights.py @@ -7,7 +7,8 @@ from homeassistant.components.light import ( from homeassistant.const import ATTR_SUPPORTED_FEATURES, STATE_ON, STATE_OFF from . import TYPES -from .accessories import HomeAccessory, add_preload_service, debounce +from .accessories import ( + HomeAccessory, add_preload_service, debounce, setup_char) from .const import ( CATEGORY_LIGHT, SERV_LIGHTBULB, CHAR_COLOR_TEMPERATURE, CHAR_BRIGHTNESS, CHAR_HUE, CHAR_ON, CHAR_SATURATION) @@ -24,12 +25,9 @@ class Light(HomeAccessory): Currently supports: state, brightness, color temperature, rgb_color. """ - def __init__(self, hass, entity_id, name, **kwargs): + def __init__(self, *args, config): """Initialize a new Light accessory object.""" - super().__init__(name, entity_id, CATEGORY_LIGHT, **kwargs) - - self.hass = hass - self.entity_id = entity_id + super().__init__(*args, category=CATEGORY_LIGHT) self._flag = {CHAR_ON: False, CHAR_BRIGHTNESS: False, CHAR_HUE: False, CHAR_SATURATION: False, CHAR_COLOR_TEMPERATURE: False, RGB_COLOR: False} @@ -49,36 +47,29 @@ class Light(HomeAccessory): self._saturation = None serv_light = add_preload_service(self, SERV_LIGHTBULB, self.chars) - self.char_on = serv_light.get_characteristic(CHAR_ON) - self.char_on.setter_callback = self.set_state - self.char_on.value = self._state + self.char_on = setup_char( + CHAR_ON, serv_light, value=self._state, callback=self.set_state) if CHAR_BRIGHTNESS in self.chars: - self.char_brightness = serv_light \ - .get_characteristic(CHAR_BRIGHTNESS) - self.char_brightness.setter_callback = self.set_brightness - self.char_brightness.value = 0 + self.char_brightness = setup_char( + CHAR_BRIGHTNESS, serv_light, value=0, + callback=self.set_brightness) if CHAR_COLOR_TEMPERATURE in self.chars: - self.char_color_temperature = serv_light \ - .get_characteristic(CHAR_COLOR_TEMPERATURE) - self.char_color_temperature.setter_callback = \ - self.set_color_temperature min_mireds = self.hass.states.get(self.entity_id) \ .attributes.get(ATTR_MIN_MIREDS, 153) max_mireds = self.hass.states.get(self.entity_id) \ .attributes.get(ATTR_MAX_MIREDS, 500) - self.char_color_temperature.override_properties({ - 'minValue': min_mireds, 'maxValue': max_mireds}) - self.char_color_temperature.value = min_mireds + self.char_color_temperature = setup_char( + CHAR_COLOR_TEMPERATURE, serv_light, value=min_mireds, + properties={'minValue': min_mireds, 'maxValue': max_mireds}, + callback=self.set_color_temperature) if CHAR_HUE in self.chars: - self.char_hue = serv_light.get_characteristic(CHAR_HUE) - self.char_hue.setter_callback = self.set_hue - self.char_hue.value = 0 + self.char_hue = setup_char( + CHAR_HUE, serv_light, value=0, callback=self.set_hue) if CHAR_SATURATION in self.chars: - self.char_saturation = serv_light \ - .get_characteristic(CHAR_SATURATION) - self.char_saturation.setter_callback = self.set_saturation - self.char_saturation.value = 75 + self.char_saturation = setup_char( + CHAR_SATURATION, serv_light, value=75, + callback=self.set_saturation) def set_state(self, value): """Set state if call came from HomeKit.""" @@ -136,11 +127,8 @@ class Light(HomeAccessory): self.hass.components.light.turn_on( self.entity_id, hs_color=color) - def update_state(self, entity_id=None, old_state=None, new_state=None): + def update_state(self, new_state): """Update light after state change.""" - if not new_state: - return - # Handle State state = new_state.state if state in (STATE_ON, STATE_OFF): @@ -162,7 +150,8 @@ class Light(HomeAccessory): if CHAR_COLOR_TEMPERATURE in self.chars: color_temperature = new_state.attributes.get(ATTR_COLOR_TEMP) if not self._flag[CHAR_COLOR_TEMPERATURE] \ - and isinstance(color_temperature, int): + and isinstance(color_temperature, int) and \ + self.char_color_temperature.value != color_temperature: self.char_color_temperature.set_value(color_temperature) self._flag[CHAR_COLOR_TEMPERATURE] = False diff --git a/homeassistant/components/homekit/type_locks.py b/homeassistant/components/homekit/type_locks.py index 9df0c101eff..f34fc6c6a7f 100644 --- a/homeassistant/components/homekit/type_locks.py +++ b/homeassistant/components/homekit/type_locks.py @@ -5,7 +5,7 @@ from homeassistant.components.lock import ( ATTR_ENTITY_ID, STATE_LOCKED, STATE_UNLOCKED, STATE_UNKNOWN) from . import TYPES -from .accessories import HomeAccessory, add_preload_service +from .accessories import HomeAccessory, add_preload_service, setup_char from .const import ( CATEGORY_LOCK, SERV_LOCK, CHAR_LOCK_CURRENT_STATE, CHAR_LOCK_TARGET_STATE) @@ -27,25 +27,18 @@ class Lock(HomeAccessory): The lock entity must support: unlock and lock. """ - def __init__(self, hass, entity_id, name, **kwargs): + def __init__(self, *args, config): """Initialize a Lock accessory object.""" - super().__init__(name, entity_id, CATEGORY_LOCK, **kwargs) - - self.hass = hass - self.entity_id = entity_id - + super().__init__(*args, category=CATEGORY_LOCK) self.flag_target_state = False serv_lock_mechanism = add_preload_service(self, SERV_LOCK) - self.char_current_state = serv_lock_mechanism. \ - get_characteristic(CHAR_LOCK_CURRENT_STATE) - self.char_target_state = serv_lock_mechanism. \ - get_characteristic(CHAR_LOCK_TARGET_STATE) - - self.char_current_state.value = HASS_TO_HOMEKIT[STATE_UNKNOWN] - self.char_target_state.value = HASS_TO_HOMEKIT[STATE_LOCKED] - - self.char_target_state.setter_callback = self.set_state + self.char_current_state = setup_char( + CHAR_LOCK_CURRENT_STATE, serv_lock_mechanism, + value=HASS_TO_HOMEKIT[STATE_UNKNOWN]) + self.char_target_state = setup_char( + CHAR_LOCK_TARGET_STATE, serv_lock_mechanism, + value=HASS_TO_HOMEKIT[STATE_LOCKED], callback=self.set_state) def set_state(self, value): """Set lock state to value if call came from HomeKit.""" @@ -58,11 +51,8 @@ class Lock(HomeAccessory): params = {ATTR_ENTITY_ID: self.entity_id} self.hass.services.call('lock', service, params) - def update_state(self, entity_id=None, old_state=None, new_state=None): + def update_state(self, new_state): """Update lock after state changed.""" - if new_state is None: - return - hass_state = new_state.state if hass_state in HASS_TO_HOMEKIT: current_lock_state = HASS_TO_HOMEKIT[hass_state] diff --git a/homeassistant/components/homekit/type_security_systems.py b/homeassistant/components/homekit/type_security_systems.py index 0c3c3e42d4b..6b8457a3aa5 100644 --- a/homeassistant/components/homekit/type_security_systems.py +++ b/homeassistant/components/homekit/type_security_systems.py @@ -7,7 +7,7 @@ from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_CODE) from . import TYPES -from .accessories import HomeAccessory, add_preload_service +from .accessories import HomeAccessory, add_preload_service, setup_char from .const import ( CATEGORY_ALARM_SYSTEM, SERV_SECURITY_SYSTEM, CHAR_CURRENT_SECURITY_STATE, CHAR_TARGET_SECURITY_STATE) @@ -27,26 +27,18 @@ STATE_TO_SERVICE = {STATE_ALARM_DISARMED: 'alarm_disarm', class SecuritySystem(HomeAccessory): """Generate an SecuritySystem accessory for an alarm control panel.""" - def __init__(self, hass, entity_id, display_name, alarm_code, **kwargs): + def __init__(self, *args, config): """Initialize a SecuritySystem accessory object.""" - super().__init__(display_name, entity_id, - CATEGORY_ALARM_SYSTEM, **kwargs) - - self.hass = hass - self.entity_id = entity_id - self._alarm_code = alarm_code - + super().__init__(*args, category=CATEGORY_ALARM_SYSTEM) + self._alarm_code = config[ATTR_CODE] self.flag_target_state = False serv_alarm = add_preload_service(self, SERV_SECURITY_SYSTEM) - self.char_current_state = serv_alarm. \ - get_characteristic(CHAR_CURRENT_SECURITY_STATE) - self.char_current_state.value = 3 - self.char_target_state = serv_alarm. \ - get_characteristic(CHAR_TARGET_SECURITY_STATE) - self.char_target_state.value = 3 - - self.char_target_state.setter_callback = self.set_security_state + self.char_current_state = setup_char( + CHAR_CURRENT_SECURITY_STATE, serv_alarm, value=3) + self.char_target_state = setup_char( + CHAR_TARGET_SECURITY_STATE, serv_alarm, value=3, + callback=self.set_security_state) def set_security_state(self, value): """Move security state to value if call came from HomeKit.""" @@ -61,11 +53,8 @@ class SecuritySystem(HomeAccessory): params[ATTR_CODE] = self._alarm_code self.hass.services.call('alarm_control_panel', service, params) - def update_state(self, entity_id=None, old_state=None, new_state=None): + def update_state(self, new_state): """Update security state after state changed.""" - if new_state is None: - return - hass_state = new_state.state if hass_state in HASS_TO_HOMEKIT: current_security_state = HASS_TO_HOMEKIT[hass_state] diff --git a/homeassistant/components/homekit/type_sensors.py b/homeassistant/components/homekit/type_sensors.py index b25eb784d6b..790f0de6103 100755 --- a/homeassistant/components/homekit/type_sensors.py +++ b/homeassistant/components/homekit/type_sensors.py @@ -6,7 +6,7 @@ from homeassistant.const import ( ATTR_DEVICE_CLASS, STATE_ON, STATE_HOME) from . import TYPES -from .accessories import HomeAccessory, add_preload_service +from .accessories import HomeAccessory, add_preload_service, setup_char from .const import ( CATEGORY_SENSOR, SERV_HUMIDITY_SENSOR, SERV_TEMPERATURE_SENSOR, CHAR_CURRENT_HUMIDITY, CHAR_CURRENT_TEMPERATURE, PROP_CELSIUS, @@ -20,10 +20,8 @@ from .const import ( DEVICE_CLASS_SMOKE, SERV_SMOKE_SENSOR, CHAR_SMOKE_DETECTED) from .util import convert_to_float, temperature_to_homekit - _LOGGER = logging.getLogger(__name__) - BINARY_SENSOR_SERVICE_MAP = { DEVICE_CLASS_CO2: (SERV_CARBON_DIOXIDE_SENSOR, CHAR_CARBON_DIOXIDE_DETECTED), @@ -43,24 +41,17 @@ class TemperatureSensor(HomeAccessory): Sensor entity must return temperature in °C, °F. """ - def __init__(self, hass, entity_id, name, **kwargs): + def __init__(self, *args, config): """Initialize a TemperatureSensor accessory object.""" - super().__init__(name, entity_id, CATEGORY_SENSOR, **kwargs) - - self.hass = hass - self.entity_id = entity_id - + super().__init__(*args, category=CATEGORY_SENSOR) serv_temp = add_preload_service(self, SERV_TEMPERATURE_SENSOR) - self.char_temp = serv_temp.get_characteristic(CHAR_CURRENT_TEMPERATURE) - self.char_temp.override_properties(properties=PROP_CELSIUS) - self.char_temp.value = 0 + self.char_temp = setup_char( + CHAR_CURRENT_TEMPERATURE, serv_temp, value=0, + properties=PROP_CELSIUS) self.unit = None - def update_state(self, entity_id=None, old_state=None, new_state=None): + def update_state(self, new_state): """Update temperature after state changed.""" - if new_state is None: - return - unit = new_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS) temperature = convert_to_float(new_state.state) if temperature: @@ -74,23 +65,15 @@ class TemperatureSensor(HomeAccessory): class HumiditySensor(HomeAccessory): """Generate a HumiditySensor accessory as humidity sensor.""" - def __init__(self, hass, entity_id, name, *args, **kwargs): + def __init__(self, *args, config): """Initialize a HumiditySensor accessory object.""" - super().__init__(name, entity_id, CATEGORY_SENSOR, *args, **kwargs) - - self.hass = hass - self.entity_id = entity_id - + super().__init__(*args, category=CATEGORY_SENSOR) serv_humidity = add_preload_service(self, SERV_HUMIDITY_SENSOR) - self.char_humidity = serv_humidity \ - .get_characteristic(CHAR_CURRENT_HUMIDITY) - self.char_humidity.value = 0 + self.char_humidity = setup_char( + CHAR_CURRENT_HUMIDITY, serv_humidity, value=0) - def update_state(self, entity_id=None, old_state=None, new_state=None): + def update_state(self, new_state): """Update accessory after state change.""" - if new_state is None: - return - humidity = convert_to_float(new_state.state) if humidity: self.char_humidity.set_value(humidity) @@ -102,28 +85,20 @@ class HumiditySensor(HomeAccessory): class BinarySensor(HomeAccessory): """Generate a BinarySensor accessory as binary sensor.""" - def __init__(self, hass, entity_id, name, **kwargs): + def __init__(self, *args, config): """Initialize a BinarySensor accessory object.""" - super().__init__(name, entity_id, CATEGORY_SENSOR, **kwargs) - - self.hass = hass - self.entity_id = entity_id - - device_class = hass.states.get(entity_id).attributes \ + super().__init__(*args, category=CATEGORY_SENSOR) + device_class = self.hass.states.get(self.entity_id).attributes \ .get(ATTR_DEVICE_CLASS) service_char = BINARY_SENSOR_SERVICE_MAP[device_class] \ if device_class in BINARY_SENSOR_SERVICE_MAP \ else BINARY_SENSOR_SERVICE_MAP[DEVICE_CLASS_OCCUPANCY] service = add_preload_service(self, service_char[0]) - self.char_detected = service.get_characteristic(service_char[1]) - self.char_detected.value = 0 + self.char_detected = setup_char(service_char[1], service, value=0) - def update_state(self, entity_id=None, old_state=None, new_state=None): + def update_state(self, new_state): """Update accessory after state change.""" - if new_state is None: - return - state = new_state.state detected = (state == STATE_ON) or (state == STATE_HOME) self.char_detected.set_value(detected) diff --git a/homeassistant/components/homekit/type_switches.py b/homeassistant/components/homekit/type_switches.py index 854cb49d181..aaf13e4ea7e 100644 --- a/homeassistant/components/homekit/type_switches.py +++ b/homeassistant/components/homekit/type_switches.py @@ -6,7 +6,7 @@ from homeassistant.const import ( from homeassistant.core import split_entity_id from . import TYPES -from .accessories import HomeAccessory, add_preload_service +from .accessories import HomeAccessory, add_preload_service, setup_char from .const import CATEGORY_SWITCH, SERV_SWITCH, CHAR_ON _LOGGER = logging.getLogger(__name__) @@ -16,20 +16,15 @@ _LOGGER = logging.getLogger(__name__) class Switch(HomeAccessory): """Generate a Switch accessory.""" - def __init__(self, hass, entity_id, display_name, **kwargs): + def __init__(self, *args, config): """Initialize a Switch accessory object to represent a remote.""" - super().__init__(display_name, entity_id, CATEGORY_SWITCH, **kwargs) - - self.hass = hass - self.entity_id = entity_id - self._domain = split_entity_id(entity_id)[0] - + super().__init__(*args, category=CATEGORY_SWITCH) + self._domain = split_entity_id(self.entity_id)[0] self.flag_target_state = False serv_switch = add_preload_service(self, SERV_SWITCH) - self.char_on = serv_switch.get_characteristic(CHAR_ON) - self.char_on.value = False - self.char_on.setter_callback = self.set_state + self.char_on = setup_char( + CHAR_ON, serv_switch, value=False, callback=self.set_state) def set_state(self, value): """Move switch state to value if call came from HomeKit.""" @@ -40,15 +35,11 @@ class Switch(HomeAccessory): self.hass.services.call(self._domain, service, {ATTR_ENTITY_ID: self.entity_id}) - def update_state(self, entity_id=None, old_state=None, new_state=None): + def update_state(self, new_state): """Update switch state after state changed.""" - if new_state is None: - return - current_state = (new_state.state == STATE_ON) if not self.flag_target_state: _LOGGER.debug('%s: Set current state to %s', self.entity_id, current_state) self.char_on.set_value(current_state) - self.flag_target_state = False diff --git a/homeassistant/components/homekit/type_thermostats.py b/homeassistant/components/homekit/type_thermostats.py index daf81c51c4d..ce10b96c51c 100644 --- a/homeassistant/components/homekit/type_thermostats.py +++ b/homeassistant/components/homekit/type_thermostats.py @@ -5,12 +5,15 @@ 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_TARGET_TEMPERATURE_HIGH, SUPPORT_TARGET_TEMPERATURE_LOW) from homeassistant.const import ( - ATTR_UNIT_OF_MEASUREMENT, STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT) + ATTR_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, + STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT) from . import TYPES -from .accessories import HomeAccessory, add_preload_service, debounce +from .accessories import ( + HomeAccessory, add_preload_service, debounce, setup_char) from .const import ( CATEGORY_THERMOSTAT, SERV_THERMOSTAT, CHAR_CURRENT_HEATING_COOLING, CHAR_TARGET_HEATING_COOLING, CHAR_CURRENT_TEMPERATURE, @@ -26,74 +29,63 @@ HC_HASS_TO_HOMEKIT = {STATE_OFF: 0, STATE_HEAT: 1, STATE_COOL: 2, STATE_AUTO: 3} HC_HOMEKIT_TO_HASS = {c: s for s, c in HC_HASS_TO_HOMEKIT.items()} +SUPPORT_TEMP_RANGE = SUPPORT_TARGET_TEMPERATURE_LOW | \ + SUPPORT_TARGET_TEMPERATURE_HIGH + @TYPES.register('Thermostat') class Thermostat(HomeAccessory): """Generate a Thermostat accessory for a climate.""" - def __init__(self, hass, entity_id, display_name, support_auto, **kwargs): + def __init__(self, *args, config): """Initialize a Thermostat accessory object.""" - super().__init__(display_name, entity_id, - CATEGORY_THERMOSTAT, **kwargs) - - self.hass = hass - self.entity_id = entity_id - self._call_timer = None + super().__init__(*args, category=CATEGORY_THERMOSTAT) self._unit = TEMP_CELSIUS - self.heat_cool_flag_target_state = False self.temperature_flag_target_state = False self.coolingthresh_flag_target_state = False self.heatingthresh_flag_target_state = False # Add additional characteristics if auto mode is supported - extra_chars = [ - CHAR_COOLING_THRESHOLD_TEMPERATURE, - CHAR_HEATING_THRESHOLD_TEMPERATURE] if support_auto else None + self.chars = [] + features = self.hass.states.get(self.entity_id) \ + .attributes.get(ATTR_SUPPORTED_FEATURES) + if features & SUPPORT_TEMP_RANGE: + self.chars.extend((CHAR_COOLING_THRESHOLD_TEMPERATURE, + CHAR_HEATING_THRESHOLD_TEMPERATURE)) - # Preload the thermostat service - serv_thermostat = add_preload_service(self, SERV_THERMOSTAT, - extra_chars) + serv_thermostat = add_preload_service( + self, SERV_THERMOSTAT, self.chars) # Current and target mode characteristics - self.char_current_heat_cool = serv_thermostat. \ - get_characteristic(CHAR_CURRENT_HEATING_COOLING) - self.char_current_heat_cool.value = 0 - self.char_target_heat_cool = serv_thermostat. \ - get_characteristic(CHAR_TARGET_HEATING_COOLING) - self.char_target_heat_cool.value = 0 - self.char_target_heat_cool.setter_callback = self.set_heat_cool + self.char_current_heat_cool = setup_char( + CHAR_CURRENT_HEATING_COOLING, serv_thermostat, value=0) + self.char_target_heat_cool = setup_char( + CHAR_TARGET_HEATING_COOLING, serv_thermostat, value=0, + callback=self.set_heat_cool) # Current and target temperature characteristics - self.char_current_temp = serv_thermostat. \ - get_characteristic(CHAR_CURRENT_TEMPERATURE) - self.char_current_temp.value = 21.0 - self.char_target_temp = serv_thermostat. \ - get_characteristic(CHAR_TARGET_TEMPERATURE) - self.char_target_temp.value = 21.0 - self.char_target_temp.setter_callback = self.set_target_temperature + self.char_current_temp = setup_char( + CHAR_CURRENT_TEMPERATURE, serv_thermostat, value=21.0) + self.char_target_temp = setup_char( + CHAR_TARGET_TEMPERATURE, serv_thermostat, value=21.0, + callback=self.set_target_temperature) # Display units characteristic - self.char_display_units = serv_thermostat. \ - get_characteristic(CHAR_TEMP_DISPLAY_UNITS) - self.char_display_units.value = 0 + self.char_display_units = setup_char( + CHAR_TEMP_DISPLAY_UNITS, serv_thermostat, value=0) # If the device supports it: high and low temperature characteristics - if support_auto: - self.char_cooling_thresh_temp = serv_thermostat. \ - get_characteristic(CHAR_COOLING_THRESHOLD_TEMPERATURE) - self.char_cooling_thresh_temp.value = 23.0 - self.char_cooling_thresh_temp.setter_callback = \ - self.set_cooling_threshold - - self.char_heating_thresh_temp = serv_thermostat. \ - get_characteristic(CHAR_HEATING_THRESHOLD_TEMPERATURE) - self.char_heating_thresh_temp.value = 19.0 - self.char_heating_thresh_temp.setter_callback = \ - self.set_heating_threshold - else: - self.char_cooling_thresh_temp = None - self.char_heating_thresh_temp = None + self.char_cooling_thresh_temp = None + self.char_heating_thresh_temp = None + if CHAR_COOLING_THRESHOLD_TEMPERATURE in self.chars: + self.char_cooling_thresh_temp = setup_char( + CHAR_COOLING_THRESHOLD_TEMPERATURE, serv_thermostat, + value=23.0, callback=self.set_cooling_threshold) + if CHAR_HEATING_THRESHOLD_TEMPERATURE in self.chars: + self.char_heating_thresh_temp = setup_char( + CHAR_HEATING_THRESHOLD_TEMPERATURE, serv_thermostat, + value=19.0, callback=self.set_heating_threshold) def set_heat_cool(self, value): """Move operation mode to value if call came from HomeKit.""" @@ -141,11 +133,8 @@ class Thermostat(HomeAccessory): self.hass.components.climate.set_temperature( temperature=value, entity_id=self.entity_id) - def update_state(self, entity_id=None, old_state=None, new_state=None): + def update_state(self, new_state): """Update security state after state changed.""" - if new_state is None: - return - self._unit = new_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS) diff --git a/homeassistant/components/homekit/util.py b/homeassistant/components/homekit/util.py index af2c74d9c3c..e14b6c47bc8 100644 --- a/homeassistant/components/homekit/util.py +++ b/homeassistant/components/homekit/util.py @@ -33,7 +33,7 @@ def validate_entity_config(values): return entities -def show_setup_message(bridge, hass): +def show_setup_message(hass, bridge): """Display persistent notification with setup information.""" pin = bridge.pincode.decode() _LOGGER.info('Pincode: %s', pin) diff --git a/tests/components/homekit/test_accessories.py b/tests/components/homekit/test_accessories.py index b7bf625a2d6..f8e026483aa 100644 --- a/tests/components/homekit/test_accessories.py +++ b/tests/components/homekit/test_accessories.py @@ -10,9 +10,8 @@ from homeassistant.components.homekit.accessories import ( add_preload_service, set_accessory_info, debounce, HomeAccessory, HomeBridge, HomeDriver) from homeassistant.components.homekit.const import ( - ACCESSORY_MODEL, ACCESSORY_NAME, BRIDGE_MODEL, BRIDGE_NAME, - SERV_ACCESSORY_INFO, CHAR_MANUFACTURER, CHAR_MODEL, - CHAR_NAME, CHAR_SERIAL_NUMBER) + BRIDGE_MODEL, BRIDGE_NAME, SERV_ACCESSORY_INFO, + CHAR_MANUFACTURER, CHAR_MODEL, CHAR_NAME, CHAR_SERIAL_NUMBER) from homeassistant.const import ATTR_NOW, EVENT_TIME_CHANGED import homeassistant.util.dt as dt_util @@ -92,7 +91,7 @@ class TestAccessories(unittest.TestCase): def test_set_accessory_info(self): """Test setting the basic accessory information.""" # Test HomeAccessory - acc = HomeAccessory() + acc = HomeAccessory('HA', 'Home Accessory', 'homekit.accessory', 2, '') set_accessory_info(acc, 'name', 'model', 'manufacturer', '0000') serv = acc.get_service(SERV_ACCESSORY_INFO) @@ -104,7 +103,7 @@ class TestAccessories(unittest.TestCase): serv.get_characteristic(CHAR_SERIAL_NUMBER).value, '0000') # Test HomeBridge - acc = HomeBridge(None) + acc = HomeBridge('hass') set_accessory_info(acc, 'name', 'model', 'manufacturer', '0000') serv = acc.get_service(SERV_ACCESSORY_INFO) @@ -116,26 +115,37 @@ class TestAccessories(unittest.TestCase): def test_home_accessory(self): """Test HomeAccessory class.""" - acc = HomeAccessory() - self.assertEqual(acc.display_name, ACCESSORY_NAME) + hass = get_test_home_assistant() + + acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory', 2, '') + self.assertEqual(acc.hass, hass) + self.assertEqual(acc.display_name, 'Home Accessory') self.assertEqual(acc.category, 1) # Category.OTHER self.assertEqual(len(acc.services), 1) serv = acc.services[0] # SERV_ACCESSORY_INFO self.assertEqual( - serv.get_characteristic(CHAR_MODEL).value, ACCESSORY_MODEL) + serv.get_characteristic(CHAR_MODEL).value, 'homekit.accessory') - acc = HomeAccessory('test_name', 'test_model', 'FAN', aid=2) + hass.states.set('homekit.accessory', 'on') + hass.block_till_done() + acc.run() + hass.states.set('homekit.accessory', 'off') + hass.block_till_done() + + acc = HomeAccessory('hass', 'test_name', 'test_model', 2, '') self.assertEqual(acc.display_name, 'test_name') - self.assertEqual(acc.category, 3) # Category.FAN self.assertEqual(acc.aid, 2) self.assertEqual(len(acc.services), 1) serv = acc.services[0] # SERV_ACCESSORY_INFO self.assertEqual( serv.get_characteristic(CHAR_MODEL).value, 'test_model') + hass.stop() + def test_home_bridge(self): """Test HomeBridge class.""" - bridge = HomeBridge(None) + bridge = HomeBridge('hass') + self.assertEqual(bridge.hass, 'hass') self.assertEqual(bridge.display_name, BRIDGE_NAME) self.assertEqual(bridge.category, 2) # Category.BRIDGE self.assertEqual(len(bridge.services), 1) @@ -144,12 +154,10 @@ class TestAccessories(unittest.TestCase): self.assertEqual( serv.get_characteristic(CHAR_MODEL).value, BRIDGE_MODEL) - bridge = HomeBridge('hass', 'test_name', 'test_model') + bridge = HomeBridge('hass', 'test_name') self.assertEqual(bridge.display_name, 'test_name') self.assertEqual(len(bridge.services), 1) serv = bridge.services[0] # SERV_ACCESSORY_INFO - self.assertEqual( - serv.get_characteristic(CHAR_MODEL).value, 'test_model') # setup_message bridge.setup_message() @@ -174,11 +182,11 @@ class TestAccessories(unittest.TestCase): self.assertEqual( mock_remove_paired_client.call_args, call('client_uuid')) - self.assertEqual(mock_show_msg.call_args, call(bridge, 'hass')) + self.assertEqual(mock_show_msg.call_args, call('hass', bridge)) def test_home_driver(self): """Test HomeDriver class.""" - bridge = HomeBridge(None) + bridge = HomeBridge('hass') ip_address = '127.0.0.1' port = 51826 path = '.homekit.state' diff --git a/tests/components/homekit/test_get_accessories.py b/tests/components/homekit/test_get_accessories.py index e323431ac3f..6f2521fc4e5 100644 --- a/tests/components/homekit/test_get_accessories.py +++ b/tests/components/homekit/test_get_accessories.py @@ -19,14 +19,14 @@ CONFIG = {} def test_get_accessory_invalid_aid(caplog): """Test with unsupported component.""" assert get_accessory(None, State('light.demo', 'on'), - aid=None, config=None) is None + None, config=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'), aid=2, config=None) \ + assert get_accessory(None, State('demo.demo', 'on'), 2, config=None) \ is None @@ -48,7 +48,6 @@ class TestGetAccessories(unittest.TestCase): {ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}) get_accessory(None, state, 2, {}) - # pylint: disable=invalid-name def test_sensor_temperature_fahrenheit(self): """Test temperature sensor with Fahrenheit as unit.""" with patch.dict(TYPES, {'TemperatureSensor': self.mock_type}): @@ -91,8 +90,9 @@ class TestGetAccessories(unittest.TestCase): get_accessory(None, state, 2, config) # pylint: disable=unsubscriptable-object + print(self.mock_type.call_args[1]) self.assertEqual( - self.mock_type.call_args[1].get('alarm_code'), '1234') + self.mock_type.call_args[1]['config'][ATTR_CODE], '1234') def test_climate(self): """Test climate devices.""" @@ -100,10 +100,6 @@ class TestGetAccessories(unittest.TestCase): state = State('climate.test', 'auto') get_accessory(None, state, 2, {}) - # pylint: disable=unsubscriptable-object - self.assertEqual( - self.mock_type.call_args[0][-1], False) # support_auto - def test_light(self): """Test light devices.""" with patch.dict(TYPES, {'Light': self.mock_type}): @@ -119,10 +115,6 @@ class TestGetAccessories(unittest.TestCase): SUPPORT_TARGET_TEMPERATURE_HIGH}) get_accessory(None, state, 2, {}) - # pylint: disable=unsubscriptable-object - self.assertEqual( - self.mock_type.call_args[0][-1], True) # support_auto - def test_switch(self): """Test switch.""" with patch.dict(TYPES, {'Switch': self.mock_type}): @@ -140,3 +132,9 @@ class TestGetAccessories(unittest.TestCase): with patch.dict(TYPES, {'Switch': self.mock_type}): state = State('input_boolean.test', 'on') get_accessory(None, state, 2, {}) + + def test_lock(self): + """Test lock.""" + with patch.dict(TYPES, {'Lock': self.mock_type}): + state = State('lock.test', 'locked') + get_accessory(None, state, 2, {}) diff --git a/tests/components/homekit/test_homekit.py b/tests/components/homekit/test_homekit.py index 51a965b5817..d1ad232d279 100644 --- a/tests/components/homekit/test_homekit.py +++ b/tests/components/homekit/test_homekit.py @@ -173,7 +173,7 @@ class TestHomeKit(unittest.TestCase): self.assertEqual(mock_add_bridge_acc.mock_calls, [call(state)]) self.assertEqual(mock_show_setup_msg.mock_calls, [ - call(homekit.bridge, self.hass)]) + call(self.hass, homekit.bridge)]) self.assertEqual(homekit.driver.mock_calls, [call.start()]) self.assertTrue(homekit.started) diff --git a/tests/components/homekit/test_type_covers.py b/tests/components/homekit/test_type_covers.py index 1fa1ef1728e..8e26ab519d1 100644 --- a/tests/components/homekit/test_type_covers.py +++ b/tests/components/homekit/test_type_covers.py @@ -35,7 +35,7 @@ class TestHomekitSensors(unittest.TestCase): """Test if accessory and HA are updated accordingly.""" window_cover = 'cover.window' - acc = WindowCovering(self.hass, window_cover, 'Cover', aid=2) + acc = WindowCovering(self.hass, 'Cover', window_cover, 2, config=None) acc.run() self.assertEqual(acc.aid, 2) diff --git a/tests/components/homekit/test_type_lights.py b/tests/components/homekit/test_type_lights.py index af8676dfd74..10bf469c08d 100644 --- a/tests/components/homekit/test_type_lights.py +++ b/tests/components/homekit/test_type_lights.py @@ -50,9 +50,11 @@ class TestHomekitLights(unittest.TestCase): def test_light_basic(self): """Test light with char state.""" entity_id = 'light.demo' + self.hass.states.set(entity_id, STATE_ON, {ATTR_SUPPORTED_FEATURES: 0}) - acc = self.light_cls(self.hass, entity_id, 'Light', aid=2) + self.hass.block_till_done() + acc = self.light_cls(self.hass, 'Light', entity_id, 2, config=None) self.assertEqual(acc.aid, 2) self.assertEqual(acc.category, 5) # Lightbulb self.assertEqual(acc.char_on.value, 0) @@ -94,9 +96,11 @@ class TestHomekitLights(unittest.TestCase): def test_light_brightness(self): """Test light with brightness.""" entity_id = 'light.demo' + self.hass.states.set(entity_id, STATE_ON, { ATTR_SUPPORTED_FEATURES: SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS: 255}) - acc = self.light_cls(self.hass, entity_id, 'Light', aid=2) + self.hass.block_till_done() + acc = self.light_cls(self.hass, 'Light', entity_id, 2, config=None) self.assertEqual(acc.char_brightness.value, 0) acc.run() @@ -135,10 +139,12 @@ class TestHomekitLights(unittest.TestCase): def test_light_color_temperature(self): """Test light with color temperature.""" entity_id = 'light.demo' + self.hass.states.set(entity_id, STATE_ON, { ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR_TEMP, ATTR_COLOR_TEMP: 190}) - acc = self.light_cls(self.hass, entity_id, 'Light', aid=2) + self.hass.block_till_done() + acc = self.light_cls(self.hass, 'Light', entity_id, 2, config=None) self.assertEqual(acc.char_color_temperature.value, 153) acc.run() @@ -157,10 +163,12 @@ class TestHomekitLights(unittest.TestCase): def test_light_rgb_color(self): """Test light with rgb_color.""" entity_id = 'light.demo' + self.hass.states.set(entity_id, STATE_ON, { ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR, ATTR_HS_COLOR: (260, 90)}) - acc = self.light_cls(self.hass, entity_id, 'Light', aid=2) + self.hass.block_till_done() + acc = self.light_cls(self.hass, 'Light', entity_id, 2, config=None) self.assertEqual(acc.char_hue.value, 0) self.assertEqual(acc.char_saturation.value, 75) diff --git a/tests/components/homekit/test_type_locks.py b/tests/components/homekit/test_type_locks.py index d19bcdf3ec5..b2053116060 100644 --- a/tests/components/homekit/test_type_locks.py +++ b/tests/components/homekit/test_type_locks.py @@ -33,7 +33,7 @@ class TestHomekitSensors(unittest.TestCase): """Test if accessory and HA are updated accordingly.""" kitchen_lock = 'lock.kitchen_door' - acc = Lock(self.hass, kitchen_lock, 'Lock', aid=2) + acc = Lock(self.hass, 'Lock', kitchen_lock, 2, config=None) acc.run() self.assertEqual(acc.aid, 2) diff --git a/tests/components/homekit/test_type_security_systems.py b/tests/components/homekit/test_type_security_systems.py index 46f886c4d35..ec538ce4b50 100644 --- a/tests/components/homekit/test_type_security_systems.py +++ b/tests/components/homekit/test_type_security_systems.py @@ -35,8 +35,8 @@ class TestHomekitSecuritySystems(unittest.TestCase): """Test if accessory and HA are updated accordingly.""" acp = 'alarm_control_panel.test' - acc = SecuritySystem(self.hass, acp, 'SecuritySystem', - alarm_code='1234', aid=2) + acc = SecuritySystem(self.hass, 'SecuritySystem', acp, + 2, config={ATTR_CODE: '1234'}) acc.run() self.assertEqual(acc.aid, 2) @@ -107,8 +107,8 @@ class TestHomekitSecuritySystems(unittest.TestCase): """Test accessory if security_system doesn't require a alarm_code.""" acp = 'alarm_control_panel.test' - acc = SecuritySystem(self.hass, acp, 'SecuritySystem', - alarm_code=None, aid=2) + acc = SecuritySystem(self.hass, 'SecuritySystem', acp, + 2, config={ATTR_CODE: None}) acc.run() # Set from HomeKit diff --git a/tests/components/homekit/test_type_sensors.py b/tests/components/homekit/test_type_sensors.py index a6e178bb226..f9dfb04b37c 100644 --- a/tests/components/homekit/test_type_sensors.py +++ b/tests/components/homekit/test_type_sensors.py @@ -26,7 +26,8 @@ class TestHomekitSensors(unittest.TestCase): """Test if accessory is updated after state change.""" entity_id = 'sensor.temperature' - acc = TemperatureSensor(self.hass, entity_id, 'Temperature', aid=2) + acc = TemperatureSensor(self.hass, 'Temperature', entity_id, + 2, config=None) acc.run() self.assertEqual(acc.aid, 2) @@ -54,7 +55,7 @@ class TestHomekitSensors(unittest.TestCase): """Test if accessory is updated after state change.""" entity_id = 'sensor.humidity' - acc = HumiditySensor(self.hass, entity_id, 'Humidity', aid=2) + acc = HumiditySensor(self.hass, 'Humidity', entity_id, 2, config=None) acc.run() self.assertEqual(acc.aid, 2) @@ -78,7 +79,8 @@ class TestHomekitSensors(unittest.TestCase): {ATTR_DEVICE_CLASS: "opening"}) self.hass.block_till_done() - acc = BinarySensor(self.hass, entity_id, 'Window Opening', aid=2) + acc = BinarySensor(self.hass, 'Window Opening', entity_id, + 2, config=None) acc.run() self.assertEqual(acc.aid, 2) @@ -118,6 +120,7 @@ class TestHomekitSensors(unittest.TestCase): {ATTR_DEVICE_CLASS: device_class}) self.hass.block_till_done() - acc = BinarySensor(self.hass, entity_id, 'Binary Sensor', aid=2) + acc = BinarySensor(self.hass, 'Binary Sensor', entity_id, + 2, config=None) self.assertEqual(acc.get_service(service).display_name, service) self.assertEqual(acc.char_detected.display_name, char) diff --git a/tests/components/homekit/test_type_switches.py b/tests/components/homekit/test_type_switches.py index 7f30e457308..65b107e24cd 100644 --- a/tests/components/homekit/test_type_switches.py +++ b/tests/components/homekit/test_type_switches.py @@ -34,7 +34,7 @@ class TestHomekitSwitches(unittest.TestCase): entity_id = 'switch.test' domain = split_entity_id(entity_id)[0] - acc = Switch(self.hass, entity_id, 'Switch', aid=2) + acc = Switch(self.hass, 'Switch', entity_id, 2, config=None) acc.run() self.assertEqual(acc.aid, 2) @@ -70,7 +70,7 @@ class TestHomekitSwitches(unittest.TestCase): entity_id = 'remote.test' domain = split_entity_id(entity_id)[0] - acc = Switch(self.hass, entity_id, 'Switch', aid=2) + acc = Switch(self.hass, 'Switch', entity_id, 2, config=None) acc.run() self.assertEqual(acc.char_on.value, False) @@ -89,7 +89,7 @@ class TestHomekitSwitches(unittest.TestCase): entity_id = 'input_boolean.test' domain = split_entity_id(entity_id)[0] - acc = Switch(self.hass, entity_id, 'Switch', aid=2) + acc = Switch(self.hass, 'Switch', entity_id, 2, config=None) acc.run() self.assertEqual(acc.char_on.value, False) diff --git a/tests/components/homekit/test_type_thermostats.py b/tests/components/homekit/test_type_thermostats.py index feea5c0d01a..adc3fb018f8 100644 --- a/tests/components/homekit/test_type_thermostats.py +++ b/tests/components/homekit/test_type_thermostats.py @@ -7,8 +7,9 @@ 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, EVENT_CALL_SERVICE, ATTR_SERVICE_DATA, - ATTR_UNIT_OF_MEASUREMENT, STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT) + ATTR_SERVICE, ATTR_SERVICE_DATA, ATTR_SUPPORTED_FEATURES, + ATTR_UNIT_OF_MEASUREMENT, EVENT_CALL_SERVICE, + STATE_OFF, TEMP_CELSIUS, TEMP_FAHRENHEIT) from tests.common import get_test_home_assistant from tests.components.homekit.test_accessories import patch_debounce @@ -52,7 +53,10 @@ class TestHomekitThermostats(unittest.TestCase): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, climate, 'Climate', False, aid=2) + self.hass.states.set(climate, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 0}) + self.hass.block_till_done() + acc = self.thermostat_cls(self.hass, 'Climate', climate, + 2, config=None) acc.run() self.assertEqual(acc.aid, 2) @@ -187,7 +191,11 @@ class TestHomekitThermostats(unittest.TestCase): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, climate, 'Climate', True) + # support_auto = True + self.hass.states.set(climate, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6}) + self.hass.block_till_done() + acc = self.thermostat_cls(self.hass, 'Climate', climate, + 2, config=None) acc.run() self.assertEqual(acc.char_cooling_thresh_temp.value, 23.0) @@ -257,7 +265,11 @@ class TestHomekitThermostats(unittest.TestCase): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, climate, 'Climate', True) + # support_auto = True + self.hass.states.set(climate, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 6}) + self.hass.block_till_done() + acc = self.thermostat_cls(self.hass, 'Climate', climate, + 2, config=None) acc.run() self.hass.states.set(climate, STATE_AUTO, diff --git a/tests/components/homekit/test_util.py b/tests/components/homekit/test_util.py index d6ef5856f85..7465e9affab 100644 --- a/tests/components/homekit/test_util.py +++ b/tests/components/homekit/test_util.py @@ -58,7 +58,7 @@ class TestUtil(unittest.TestCase): """Test show setup message as persistence notification.""" bridge = HomeBridge(self.hass) - show_setup_message(bridge, self.hass) + show_setup_message(self.hass, bridge) self.hass.block_till_done() data = self.events[0].data