From 03eb379b516e4f116cf8629b16932de03ca3d1c7 Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Thu, 5 Apr 2018 21:45:06 +0200 Subject: [PATCH 01/12] Style improvements * Set argument order for HomeAccessory and HomeBridge * Added update_state_callback --- homeassistant/components/homekit/__init__.py | 41 +++++++++--------- .../components/homekit/accessories.py | 38 ++++++++++------ homeassistant/components/homekit/const.py | 2 - .../components/homekit/type_covers.py | 15 ++----- .../components/homekit/type_lights.py | 12 ++---- .../components/homekit/type_locks.py | 13 ++---- .../homekit/type_security_systems.py | 14 ++---- .../components/homekit/type_sensors.py | 43 ++++++------------- .../components/homekit/type_switches.py | 16 +++---- .../components/homekit/type_thermostats.py | 15 ++----- homeassistant/components/homekit/util.py | 2 +- tests/components/homekit/test_accessories.py | 39 ++++++++++------- .../homekit/test_get_accessories.py | 7 ++- tests/components/homekit/test_homekit.py | 2 +- tests/components/homekit/test_type_covers.py | 2 +- tests/components/homekit/test_type_lights.py | 12 ++++-- tests/components/homekit/test_type_locks.py | 2 +- .../homekit/test_type_security_systems.py | 4 +- tests/components/homekit/test_type_sensors.py | 8 ++-- .../components/homekit/test_type_switches.py | 6 +-- .../homekit/test_type_thermostats.py | 6 +-- tests/components/homekit/test_util.py | 2 +- 22 files changed, 139 insertions(+), 162 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index 22c74faf5f0a7d..4e82cb85565e7f 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -84,18 +84,18 @@ def get_accessory(hass, state, aid, config): 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) + return TYPES['TemperatureSensor'](hass, state.name, + state.entity_id, 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) + return TYPES['HumiditySensor'](hass, state.name, + state.entity_id, aid=aid) 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) + return TYPES['BinarySensor'](hass, state.name, state.entity_id, + aid=aid) elif state.domain == 'cover': # Only add covers that support set_cover_position @@ -103,12 +103,12 @@ def get_accessory(hass, state, aid, config): if features & SUPPORT_SET_POSITION: _LOGGER.debug('Add "%s" as "%s"', state.entity_id, 'WindowCovering') - return TYPES['WindowCovering'](hass, state.entity_id, state.name, + return TYPES['WindowCovering'](hass, state.name, state.entity_id, 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, + return TYPES['SecuritySystem'](hass, state.name, state.entity_id, alarm_code=config.get(ATTR_CODE), aid=aid) @@ -120,20 +120,21 @@ def get_accessory(hass, state, aid, config): 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) + return TYPES['Thermostat'](hass, state.name, state.entity_id, + support_auto, aid=aid) 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) + return TYPES['Light'](hass, state.name, state.entity_id, aid=aid) elif state.domain == 'lock': - return TYPES['Lock'](hass, state.entity_id, state.name, aid=aid) + _LOGGER.debug('Add "%s" as "%s"', state.entity_id, 'Lock') + return TYPES['Lock'](hass, state.name, state.entity_id, aid=aid) 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) + return TYPES['Switch'](hass, state.name, state.entity_id, aid=aid) return None @@ -151,7 +152,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 +165,11 @@ def setup(self): """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 +178,7 @@ def add_bridge_accessory(self, state): 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 +193,12 @@ def start(self, *args): 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 ec2c49f5e43991..573e969613d367 100644 --- a/homeassistant/components/homekit/accessories.py +++ b/homeassistant/components/homekit/accessories.py @@ -13,8 +13,8 @@ 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) @@ -85,14 +85,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, category='OTHER', **kwargs): """Initialize a Accessory object.""" super().__init__(name, **kwargs) - set_accessory_info(self, name, model) + 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 +99,32 @@ def _set_services(self): 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.""" + 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, **kwargs): """Initialize a Bridge object.""" super().__init__(name, **kwargs) - set_accessory_info(self, name, model) + set_accessory_info(self, name, model=BRIDGE_MODEL) self.hass = hass def _set_services(self): @@ -130,7 +142,7 @@ def add_paired_client(self, client_uuid, client_public): 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 e5a4c80a4301f9..80f2fd039e6063 100644 --- a/homeassistant/components/homekit/const.py +++ b/homeassistant/components/homekit/const.py @@ -18,8 +18,6 @@ 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 781f52941fcaca..947d1337c07e31 100644 --- a/homeassistant/components/homekit/type_covers.py +++ b/homeassistant/components/homekit/type_covers.py @@ -9,7 +9,6 @@ CATEGORY_WINDOW_COVERING, SERV_WINDOW_COVERING, CHAR_CURRENT_POSITION, CHAR_TARGET_POSITION, CHAR_POSITION_STATE) - _LOGGER = logging.getLogger(__name__) @@ -20,13 +19,10 @@ class WindowCovering(HomeAccessory): The cover entity must support: set_cover_position. """ - def __init__(self, hass, entity_id, display_name, **kwargs): + def __init__(self, hass, name, entity_id, **kwargs): """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__(hass, name, entity_id, + category=CATEGORY_WINDOW_COVERING, **kwargs) self.current_position = None self.homekit_target = None @@ -56,11 +52,8 @@ def move_cover(self, value): 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 4fbfb995859563..3cd2f880d22301 100644 --- a/homeassistant/components/homekit/type_lights.py +++ b/homeassistant/components/homekit/type_lights.py @@ -24,12 +24,11 @@ class Light(HomeAccessory): Currently supports: state, brightness, color temperature, rgb_color. """ - def __init__(self, hass, entity_id, name, **kwargs): + def __init__(self, hass, name, entity_id, **kwargs): """Initialize a new Light accessory object.""" - super().__init__(name, entity_id, CATEGORY_LIGHT, **kwargs) + super().__init__(hass, name, entity_id, + category=CATEGORY_LIGHT, **kwargs) - self.hass = hass - self.entity_id = entity_id self._flag = {CHAR_ON: False, CHAR_BRIGHTNESS: False, CHAR_HUE: False, CHAR_SATURATION: False, CHAR_COLOR_TEMPERATURE: False, RGB_COLOR: False} @@ -136,11 +135,8 @@ def set_color(self): 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): diff --git a/homeassistant/components/homekit/type_locks.py b/homeassistant/components/homekit/type_locks.py index 9df0c101eff494..8e732ed5325388 100644 --- a/homeassistant/components/homekit/type_locks.py +++ b/homeassistant/components/homekit/type_locks.py @@ -27,12 +27,10 @@ class Lock(HomeAccessory): The lock entity must support: unlock and lock. """ - def __init__(self, hass, entity_id, name, **kwargs): + def __init__(self, hass, name, entity_id, **kwargs): """Initialize a Lock accessory object.""" - super().__init__(name, entity_id, CATEGORY_LOCK, **kwargs) - - self.hass = hass - self.entity_id = entity_id + super().__init__(hass, name, entity_id, + category=CATEGORY_LOCK, **kwargs) self.flag_target_state = False @@ -58,11 +56,8 @@ def set_state(self, value): 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 0c3c3e42d4b94b..0e905ee53ed778 100644 --- a/homeassistant/components/homekit/type_security_systems.py +++ b/homeassistant/components/homekit/type_security_systems.py @@ -27,15 +27,12 @@ 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, hass, name, entity_id, alarm_code, **kwargs): """Initialize a SecuritySystem accessory object.""" - super().__init__(display_name, entity_id, - CATEGORY_ALARM_SYSTEM, **kwargs) + super().__init__(hass, name, entity_id, + category=CATEGORY_ALARM_SYSTEM, **kwargs) - self.hass = hass - self.entity_id = entity_id self._alarm_code = alarm_code - self.flag_target_state = False serv_alarm = add_preload_service(self, SERV_SECURITY_SYSTEM) @@ -61,11 +58,8 @@ def set_security_state(self, value): 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 b25eb784d6bde4..d9fa1a5af4c5d3 100755 --- a/homeassistant/components/homekit/type_sensors.py +++ b/homeassistant/components/homekit/type_sensors.py @@ -20,10 +20,8 @@ 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,12 +41,10 @@ class TemperatureSensor(HomeAccessory): Sensor entity must return temperature in °C, °F. """ - def __init__(self, hass, entity_id, name, **kwargs): + def __init__(self, hass, name, entity_id, **kwargs): """Initialize a TemperatureSensor accessory object.""" - super().__init__(name, entity_id, CATEGORY_SENSOR, **kwargs) - - self.hass = hass - self.entity_id = entity_id + super().__init__(hass, name, entity_id, + category=CATEGORY_SENSOR, **kwargs) serv_temp = add_preload_service(self, SERV_TEMPERATURE_SENSOR) self.char_temp = serv_temp.get_characteristic(CHAR_CURRENT_TEMPERATURE) @@ -56,11 +52,8 @@ def __init__(self, hass, entity_id, name, **kwargs): self.char_temp.value = 0 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 +67,18 @@ def update_state(self, entity_id=None, old_state=None, new_state=None): class HumiditySensor(HomeAccessory): """Generate a HumiditySensor accessory as humidity sensor.""" - def __init__(self, hass, entity_id, name, *args, **kwargs): + def __init__(self, hass, name, entity_id, **kwargs): """Initialize a HumiditySensor accessory object.""" - super().__init__(name, entity_id, CATEGORY_SENSOR, *args, **kwargs) - - self.hass = hass - self.entity_id = entity_id + super().__init__(hass, name, entity_id, + category=CATEGORY_SENSOR, **kwargs) serv_humidity = add_preload_service(self, SERV_HUMIDITY_SENSOR) self.char_humidity = serv_humidity \ .get_characteristic(CHAR_CURRENT_HUMIDITY) self.char_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,14 +90,12 @@ def update_state(self, entity_id=None, old_state=None, new_state=None): class BinarySensor(HomeAccessory): """Generate a BinarySensor accessory as binary sensor.""" - def __init__(self, hass, entity_id, name, **kwargs): + def __init__(self, hass, name, entity_id, **kwargs): """Initialize a BinarySensor accessory object.""" - super().__init__(name, entity_id, CATEGORY_SENSOR, **kwargs) + super().__init__(hass, name, entity_id, + category=CATEGORY_SENSOR, **kwargs) - self.hass = hass - self.entity_id = entity_id - - device_class = hass.states.get(entity_id).attributes \ + 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 \ @@ -119,11 +105,8 @@ def __init__(self, hass, entity_id, name, **kwargs): self.char_detected = service.get_characteristic(service_char[1]) self.char_detected.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 854cb49d1819c6..aa0de68a69cc4b 100644 --- a/homeassistant/components/homekit/type_switches.py +++ b/homeassistant/components/homekit/type_switches.py @@ -16,14 +16,12 @@ class Switch(HomeAccessory): """Generate a Switch accessory.""" - def __init__(self, hass, entity_id, display_name, **kwargs): + def __init__(self, hass, name, entity_id, **kwargs): """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__(hass, name, entity_id, + category=CATEGORY_SWITCH, **kwargs) + self._domain = split_entity_id(self.entity_id)[0] self.flag_target_state = False serv_switch = add_preload_service(self, SERV_SWITCH) @@ -40,15 +38,11 @@ def set_state(self, value): 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 daf81c51c4d937..46a32b3089eb90 100644 --- a/homeassistant/components/homekit/type_thermostats.py +++ b/homeassistant/components/homekit/type_thermostats.py @@ -31,16 +31,12 @@ class Thermostat(HomeAccessory): """Generate a Thermostat accessory for a climate.""" - def __init__(self, hass, entity_id, display_name, support_auto, **kwargs): + def __init__(self, hass, name, entity_id, support_auto, **kwargs): """Initialize a Thermostat accessory object.""" - super().__init__(display_name, entity_id, - CATEGORY_THERMOSTAT, **kwargs) + super().__init__(hass, name, entity_id, + category=CATEGORY_THERMOSTAT, **kwargs) - self.hass = hass - self.entity_id = entity_id - self._call_timer = None self._unit = TEMP_CELSIUS - self.heat_cool_flag_target_state = False self.temperature_flag_target_state = False self.coolingthresh_flag_target_state = False @@ -141,11 +137,8 @@ def set_target_temperature(self, value): 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 af2c74d9c3c665..e14b6c47bc884e 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 b7bf625a2d6452..a0cf37d9a3832f 100644 --- a/tests/components/homekit/test_accessories.py +++ b/tests/components/homekit/test_accessories.py @@ -10,9 +10,8 @@ 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 @@ def test_add_preload_service(self): def test_set_accessory_info(self): """Test setting the basic accessory information.""" # Test HomeAccessory - acc = HomeAccessory() + acc = HomeAccessory('hass', 'Home Accessory', 'homekit.accessory') set_accessory_info(acc, 'name', 'model', 'manufacturer', '0000') serv = acc.get_service(SERV_ACCESSORY_INFO) @@ -104,7 +103,7 @@ def test_set_accessory_info(self): 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,15 +115,24 @@ def test_set_accessory_info(self): 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') + 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') + + hass.states.set('homekit.accessory', 'on') + hass.block_till_done() + acc.run() + hass.states.set('homekit.accessory', 'off') + hass.block_till_done() - acc = HomeAccessory('test_name', 'test_model', 'FAN', aid=2) + acc = HomeAccessory('hass', 'test_name', 'test_model', 'FAN', aid=2) self.assertEqual(acc.display_name, 'test_name') self.assertEqual(acc.category, 3) # Category.FAN self.assertEqual(acc.aid, 2) @@ -133,9 +141,12 @@ def test_home_accessory(self): 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 +155,10 @@ def test_home_bridge(self): 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 +183,11 @@ def test_home_bridge(self): 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 e323431ac3f76f..9da77ca9f2c77e 100644 --- a/tests/components/homekit/test_get_accessories.py +++ b/tests/components/homekit/test_get_accessories.py @@ -48,7 +48,6 @@ def test_sensor_temperature_celsius(self): {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}): @@ -140,3 +139,9 @@ def test_input_boolean(self): 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 51a965b5817145..d1ad232d279359 100644 --- a/tests/components/homekit/test_homekit.py +++ b/tests/components/homekit/test_homekit.py @@ -173,7 +173,7 @@ def test_homekit_start(self, mock_add_bridge_acc, mock_show_setup_msg): 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 1fa1ef1728e04a..5ab0f06e55ba12 100644 --- a/tests/components/homekit/test_type_covers.py +++ b/tests/components/homekit/test_type_covers.py @@ -35,7 +35,7 @@ def test_window_set_cover_position(self): """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, aid=2) 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 af8676dfd742b0..9b559f714230d1 100644 --- a/tests/components/homekit/test_type_lights.py +++ b/tests/components/homekit/test_type_lights.py @@ -50,9 +50,10 @@ def tearDown(self): 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) + acc = self.light_cls(self.hass, 'Light', entity_id, aid=2) self.assertEqual(acc.aid, 2) self.assertEqual(acc.category, 5) # Lightbulb self.assertEqual(acc.char_on.value, 0) @@ -94,9 +95,10 @@ def test_light_basic(self): 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) + acc = self.light_cls(self.hass, 'Light', entity_id, aid=2) self.assertEqual(acc.char_brightness.value, 0) acc.run() @@ -135,10 +137,11 @@ def test_light_brightness(self): 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) + acc = self.light_cls(self.hass, 'Light', entity_id, aid=2) self.assertEqual(acc.char_color_temperature.value, 153) acc.run() @@ -157,10 +160,11 @@ def test_light_color_temperature(self): 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) + acc = self.light_cls(self.hass, 'Light', entity_id, aid=2) 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 d19bcdf3ec561d..23ed810954aac8 100644 --- a/tests/components/homekit/test_type_locks.py +++ b/tests/components/homekit/test_type_locks.py @@ -33,7 +33,7 @@ def test_lock_unlock(self): """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, aid=2) 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 46f886c4d35b94..324822ab2ace90 100644 --- a/tests/components/homekit/test_type_security_systems.py +++ b/tests/components/homekit/test_type_security_systems.py @@ -35,7 +35,7 @@ def test_switch_set_state(self): """Test if accessory and HA are updated accordingly.""" acp = 'alarm_control_panel.test' - acc = SecuritySystem(self.hass, acp, 'SecuritySystem', + acc = SecuritySystem(self.hass, 'SecuritySystem', acp, alarm_code='1234', aid=2) acc.run() @@ -107,7 +107,7 @@ def test_no_alarm_code(self): """Test accessory if security_system doesn't require a alarm_code.""" acp = 'alarm_control_panel.test' - acc = SecuritySystem(self.hass, acp, 'SecuritySystem', + acc = SecuritySystem(self.hass, 'SecuritySystem', acp, alarm_code=None, aid=2) acc.run() diff --git a/tests/components/homekit/test_type_sensors.py b/tests/components/homekit/test_type_sensors.py index a6e178bb226ce9..b16646626e0284 100644 --- a/tests/components/homekit/test_type_sensors.py +++ b/tests/components/homekit/test_type_sensors.py @@ -26,7 +26,7 @@ def test_temperature(self): """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, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -54,7 +54,7 @@ def test_humidity(self): """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, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -78,7 +78,7 @@ def test_binary(self): {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, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -118,6 +118,6 @@ def test_binary_device_classes(self): {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, aid=2) 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 7f30e457308692..f5a38cf9f08770 100644 --- a/tests/components/homekit/test_type_switches.py +++ b/tests/components/homekit/test_type_switches.py @@ -34,7 +34,7 @@ def test_switch_set_state(self): 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, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -70,7 +70,7 @@ def test_remote_set_state(self): 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, aid=2) acc.run() self.assertEqual(acc.char_on.value, False) @@ -89,7 +89,7 @@ def test_input_boolean_set_state(self): 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, aid=2) 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 feea5c0d01a88d..8e5dcc5e6d0d94 100644 --- a/tests/components/homekit/test_type_thermostats.py +++ b/tests/components/homekit/test_type_thermostats.py @@ -52,7 +52,7 @@ def test_default_thermostat(self): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, climate, 'Climate', False, aid=2) + acc = self.thermostat_cls(self.hass, 'Climate', climate, False, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -187,7 +187,7 @@ def test_auto_thermostat(self): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, climate, 'Climate', True) + acc = self.thermostat_cls(self.hass, 'Climate', climate, True) acc.run() self.assertEqual(acc.char_cooling_thresh_temp.value, 23.0) @@ -257,7 +257,7 @@ def test_thermostat_fahrenheit(self): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, climate, 'Climate', True) + acc = self.thermostat_cls(self.hass, 'Climate', climate, True) 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 d6ef5856f85924..7465e9affab9d8 100644 --- a/tests/components/homekit/test_util.py +++ b/tests/components/homekit/test_util.py @@ -58,7 +58,7 @@ def test_show_setup_msg(self): """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 From 5243038f9580de12e18cb2925298d04c696179b0 Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Tue, 10 Apr 2018 00:20:44 +0200 Subject: [PATCH 02/12] Rewritten get_accessory --- homeassistant/components/homekit/__init__.py | 74 ++++++++----------- .../homekit/test_get_accessories.py | 6 +- 2 files changed, 34 insertions(+), 46 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index 4e82cb85565e7f..1c23dd529b7093 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -77,73 +77,61 @@ def get_accessory(hass, state, aid, config): _LOGGER.warning('The entitiy "%s" is not supported, since it ' 'generates an invalid aid, please change it.', state.entity_id) - return None + return - 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.name, - state.entity_id, aid=aid) - elif unit == '%': - _LOGGER.debug('Add "%s" as %s"', - state.entity_id, 'HumiditySensor') - return TYPES['HumiditySensor'](hass, state.name, - state.entity_id, aid=aid) - - 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.name, state.entity_id, - aid=aid) + a_type = None + a_kwargs = {'aid': aid} - 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.name, state.entity_id, - aid=aid) + if state.domain == 'alarm_control_panel': + a_type = 'SecuritySystem' + a_kwargs['alarm_code'] = config.get(ATTR_CODE) - elif state.domain == 'alarm_control_panel': - _LOGGER.debug('Add "%s" as "%s"', state.entity_id, 'SecuritySystem') - return TYPES['SecuritySystem'](hass, state.name, state.entity_id, - alarm_code=config.get(ATTR_CODE), - aid=aid) + elif state.domain == 'binary_sensor' or state.domain == 'device_tracker': + a_type = 'BinarySensor' 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) + a_type = 'Thermostat' + a_kwargs['support_auto'] = bool(features & support_temp_range) - _LOGGER.debug('Add "%s" as "%s"', state.entity_id, 'Thermostat') - return TYPES['Thermostat'](hass, state.name, state.entity_id, - support_auto, aid=aid) + 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: + a_type = 'WindowCovering' elif state.domain == 'light': - _LOGGER.debug('Add "%s" as "%s"', state.entity_id, 'Light') - return TYPES['Light'](hass, state.name, state.entity_id, aid=aid) + a_type = 'Light' elif state.domain == 'lock': - _LOGGER.debug('Add "%s" as "%s"', state.entity_id, 'Lock') - return TYPES['Lock'](hass, state.name, state.entity_id, 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.name, state.entity_id, aid=aid) + a_type = 'Switch' + + if a_type is None: + return - return None + _LOGGER.debug('Add "%s" as "%s"', state.entity_id, a_type) + return TYPES[a_type](hass, state.name, state.entity_id, **a_kwargs) def generate_aid(entity_id): """Generate accessory aid with zlib adler32.""" aid = adler32(entity_id.encode('utf-8')) if aid == 0 or aid == 1: - return None + return return aid diff --git a/tests/components/homekit/test_get_accessories.py b/tests/components/homekit/test_get_accessories.py index 9da77ca9f2c77e..c1dbf07a61ed13 100644 --- a/tests/components/homekit/test_get_accessories.py +++ b/tests/components/homekit/test_get_accessories.py @@ -91,7 +91,7 @@ def test_alarm_control_panel(self): # pylint: disable=unsubscriptable-object self.assertEqual( - self.mock_type.call_args[1].get('alarm_code'), '1234') + self.mock_type.call_args[1]['alarm_code'], '1234') def test_climate(self): """Test climate devices.""" @@ -101,7 +101,7 @@ def test_climate(self): # pylint: disable=unsubscriptable-object self.assertEqual( - self.mock_type.call_args[0][-1], False) # support_auto + self.mock_type.call_args[1]['support_auto'], False) def test_light(self): """Test light devices.""" @@ -120,7 +120,7 @@ def test_climate_support_auto(self): # pylint: disable=unsubscriptable-object self.assertEqual( - self.mock_type.call_args[0][-1], True) # support_auto + self.mock_type.call_args[1]['support_auto'], True) def test_switch(self): """Test switch.""" From 8703cb2a3d4a9f540baa00534b23be2666e2a252 Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Tue, 10 Apr 2018 00:26:24 +0200 Subject: [PATCH 03/12] Added log statement --- homeassistant/components/homekit/accessories.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/homekit/accessories.py b/homeassistant/components/homekit/accessories.py index 573e969613d367..d6e678cd6f504e 100644 --- a/homeassistant/components/homekit/accessories.py +++ b/homeassistant/components/homekit/accessories.py @@ -106,6 +106,7 @@ def run(self): 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) From 2b05f1e8e434bc8ff61baa79f8ebe3a2c3195648 Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Tue, 10 Apr 2018 07:53:32 +0200 Subject: [PATCH 04/12] Return None --- homeassistant/components/homekit/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index 1c23dd529b7093..69eb9271b2ac98 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -77,7 +77,7 @@ def get_accessory(hass, state, aid, config): _LOGGER.warning('The entitiy "%s" is not supported, since it ' 'generates an invalid aid, please change it.', state.entity_id) - return + return None a_type = None a_kwargs = {'aid': aid} @@ -121,7 +121,7 @@ def get_accessory(hass, state, aid, config): a_type = 'Switch' if a_type is None: - return + return None _LOGGER.debug('Add "%s" as "%s"', state.entity_id, a_type) return TYPES[a_type](hass, state.name, state.entity_id, **a_kwargs) @@ -131,7 +131,7 @@ def generate_aid(entity_id): """Generate accessory aid with zlib adler32.""" aid = adler32(entity_id.encode('utf-8')) if aid == 0 or aid == 1: - return + return None return aid From cb0aad44683c1b43a3286172d8a660f999568e44 Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Tue, 10 Apr 2018 20:56:23 +0200 Subject: [PATCH 05/12] Pass config instead of **a_kwargs --- homeassistant/components/homekit/__init__.py | 12 ++++-------- homeassistant/components/homekit/type_covers.py | 2 +- homeassistant/components/homekit/type_lights.py | 2 +- homeassistant/components/homekit/type_locks.py | 2 +- .../components/homekit/type_security_systems.py | 4 ++-- homeassistant/components/homekit/type_sensors.py | 6 +++--- homeassistant/components/homekit/type_switches.py | 2 +- homeassistant/components/homekit/type_thermostats.py | 7 ++++--- tests/components/homekit/test_get_accessories.py | 6 +++--- tests/components/homekit/test_type_covers.py | 2 +- tests/components/homekit/test_type_lights.py | 8 ++++---- tests/components/homekit/test_type_locks.py | 2 +- .../components/homekit/test_type_security_systems.py | 4 ++-- tests/components/homekit/test_type_sensors.py | 10 ++++++---- tests/components/homekit/test_type_switches.py | 6 +++--- tests/components/homekit/test_type_thermostats.py | 9 ++++++--- 16 files changed, 43 insertions(+), 41 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index 69eb9271b2ac98..91503b4b804349 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -12,7 +12,7 @@ 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,12 +79,8 @@ def get_accessory(hass, state, aid, config): state.entity_id) return None - a_type = None - a_kwargs = {'aid': aid} - if state.domain == 'alarm_control_panel': a_type = 'SecuritySystem' - a_kwargs['alarm_code'] = config.get(ATTR_CODE) elif state.domain == 'binary_sensor' or state.domain == 'device_tracker': a_type = 'BinarySensor' @@ -95,7 +91,7 @@ def get_accessory(hass, state, aid, config): SUPPORT_TARGET_TEMPERATURE_HIGH # Check if climate device supports auto mode a_type = 'Thermostat' - a_kwargs['support_auto'] = bool(features & support_temp_range) + config['support_auto'] = bool(features & support_temp_range) elif state.domain == 'cover': # Only add covers that support set_cover_position @@ -120,11 +116,11 @@ def get_accessory(hass, state, aid, config): or state.domain == 'input_boolean' or state.domain == 'script': a_type = 'Switch' - if a_type is None: + else: return None _LOGGER.debug('Add "%s" as "%s"', state.entity_id, a_type) - return TYPES[a_type](hass, state.name, state.entity_id, **a_kwargs) + return TYPES[a_type](hass, state.name, state.entity_id, config, aid=aid) def generate_aid(entity_id): diff --git a/homeassistant/components/homekit/type_covers.py b/homeassistant/components/homekit/type_covers.py index 947d1337c07e31..7eb133a81ea20c 100644 --- a/homeassistant/components/homekit/type_covers.py +++ b/homeassistant/components/homekit/type_covers.py @@ -19,7 +19,7 @@ class WindowCovering(HomeAccessory): The cover entity must support: set_cover_position. """ - def __init__(self, hass, name, entity_id, **kwargs): + def __init__(self, hass, name, entity_id, config, **kwargs): """Initialize a WindowCovering accessory object.""" super().__init__(hass, name, entity_id, category=CATEGORY_WINDOW_COVERING, **kwargs) diff --git a/homeassistant/components/homekit/type_lights.py b/homeassistant/components/homekit/type_lights.py index 3cd2f880d22301..353f71fee0faf3 100644 --- a/homeassistant/components/homekit/type_lights.py +++ b/homeassistant/components/homekit/type_lights.py @@ -24,7 +24,7 @@ class Light(HomeAccessory): Currently supports: state, brightness, color temperature, rgb_color. """ - def __init__(self, hass, name, entity_id, **kwargs): + def __init__(self, hass, name, entity_id, config, **kwargs): """Initialize a new Light accessory object.""" super().__init__(hass, name, entity_id, category=CATEGORY_LIGHT, **kwargs) diff --git a/homeassistant/components/homekit/type_locks.py b/homeassistant/components/homekit/type_locks.py index 8e732ed5325388..d141090548ae79 100644 --- a/homeassistant/components/homekit/type_locks.py +++ b/homeassistant/components/homekit/type_locks.py @@ -27,7 +27,7 @@ class Lock(HomeAccessory): The lock entity must support: unlock and lock. """ - def __init__(self, hass, name, entity_id, **kwargs): + def __init__(self, hass, name, entity_id, config, **kwargs): """Initialize a Lock accessory object.""" super().__init__(hass, name, entity_id, category=CATEGORY_LOCK, **kwargs) diff --git a/homeassistant/components/homekit/type_security_systems.py b/homeassistant/components/homekit/type_security_systems.py index 0e905ee53ed778..ed742f3dee12fc 100644 --- a/homeassistant/components/homekit/type_security_systems.py +++ b/homeassistant/components/homekit/type_security_systems.py @@ -27,12 +27,12 @@ class SecuritySystem(HomeAccessory): """Generate an SecuritySystem accessory for an alarm control panel.""" - def __init__(self, hass, name, entity_id, alarm_code, **kwargs): + def __init__(self, hass, name, entity_id, config, **kwargs): """Initialize a SecuritySystem accessory object.""" super().__init__(hass, name, entity_id, category=CATEGORY_ALARM_SYSTEM, **kwargs) - self._alarm_code = alarm_code + self._alarm_code = config[ATTR_CODE] self.flag_target_state = False serv_alarm = add_preload_service(self, SERV_SECURITY_SYSTEM) diff --git a/homeassistant/components/homekit/type_sensors.py b/homeassistant/components/homekit/type_sensors.py index d9fa1a5af4c5d3..0e30e1809b01b2 100755 --- a/homeassistant/components/homekit/type_sensors.py +++ b/homeassistant/components/homekit/type_sensors.py @@ -41,7 +41,7 @@ class TemperatureSensor(HomeAccessory): Sensor entity must return temperature in °C, °F. """ - def __init__(self, hass, name, entity_id, **kwargs): + def __init__(self, hass, name, entity_id, config, **kwargs): """Initialize a TemperatureSensor accessory object.""" super().__init__(hass, name, entity_id, category=CATEGORY_SENSOR, **kwargs) @@ -67,7 +67,7 @@ def update_state(self, new_state): class HumiditySensor(HomeAccessory): """Generate a HumiditySensor accessory as humidity sensor.""" - def __init__(self, hass, name, entity_id, **kwargs): + def __init__(self, hass, name, entity_id, config, **kwargs): """Initialize a HumiditySensor accessory object.""" super().__init__(hass, name, entity_id, category=CATEGORY_SENSOR, **kwargs) @@ -90,7 +90,7 @@ def update_state(self, new_state): class BinarySensor(HomeAccessory): """Generate a BinarySensor accessory as binary sensor.""" - def __init__(self, hass, name, entity_id, **kwargs): + def __init__(self, hass, name, entity_id, config, **kwargs): """Initialize a BinarySensor accessory object.""" super().__init__(hass, name, entity_id, category=CATEGORY_SENSOR, **kwargs) diff --git a/homeassistant/components/homekit/type_switches.py b/homeassistant/components/homekit/type_switches.py index aa0de68a69cc4b..1c46f9e113ddb8 100644 --- a/homeassistant/components/homekit/type_switches.py +++ b/homeassistant/components/homekit/type_switches.py @@ -16,7 +16,7 @@ class Switch(HomeAccessory): """Generate a Switch accessory.""" - def __init__(self, hass, name, entity_id, **kwargs): + def __init__(self, hass, name, entity_id, config, **kwargs): """Initialize a Switch accessory object to represent a remote.""" super().__init__(hass, name, entity_id, category=CATEGORY_SWITCH, **kwargs) diff --git a/homeassistant/components/homekit/type_thermostats.py b/homeassistant/components/homekit/type_thermostats.py index 46a32b3089eb90..fbad0a55638fc8 100644 --- a/homeassistant/components/homekit/type_thermostats.py +++ b/homeassistant/components/homekit/type_thermostats.py @@ -31,12 +31,13 @@ class Thermostat(HomeAccessory): """Generate a Thermostat accessory for a climate.""" - def __init__(self, hass, name, entity_id, support_auto, **kwargs): + def __init__(self, hass, name, entity_id, config, **kwargs): """Initialize a Thermostat accessory object.""" super().__init__(hass, name, entity_id, category=CATEGORY_THERMOSTAT, **kwargs) self._unit = TEMP_CELSIUS + self._support_auto = config['support_auto'] self.heat_cool_flag_target_state = False self.temperature_flag_target_state = False self.coolingthresh_flag_target_state = False @@ -45,7 +46,7 @@ def __init__(self, hass, name, entity_id, support_auto, **kwargs): # Add additional characteristics if auto mode is supported extra_chars = [ CHAR_COOLING_THRESHOLD_TEMPERATURE, - CHAR_HEATING_THRESHOLD_TEMPERATURE] if support_auto else None + CHAR_HEATING_THRESHOLD_TEMPERATURE] if self._support_auto else None # Preload the thermostat service serv_thermostat = add_preload_service(self, SERV_THERMOSTAT, @@ -75,7 +76,7 @@ def __init__(self, hass, name, entity_id, support_auto, **kwargs): self.char_display_units.value = 0 # If the device supports it: high and low temperature characteristics - if support_auto: + if self._support_auto: self.char_cooling_thresh_temp = serv_thermostat. \ get_characteristic(CHAR_COOLING_THRESHOLD_TEMPERATURE) self.char_cooling_thresh_temp.value = 23.0 diff --git a/tests/components/homekit/test_get_accessories.py b/tests/components/homekit/test_get_accessories.py index c1dbf07a61ed13..68ef4919b5ff09 100644 --- a/tests/components/homekit/test_get_accessories.py +++ b/tests/components/homekit/test_get_accessories.py @@ -91,7 +91,7 @@ def test_alarm_control_panel(self): # pylint: disable=unsubscriptable-object self.assertEqual( - self.mock_type.call_args[1]['alarm_code'], '1234') + self.mock_type.call_args[0][-1][ATTR_CODE], '1234') def test_climate(self): """Test climate devices.""" @@ -101,7 +101,7 @@ def test_climate(self): # pylint: disable=unsubscriptable-object self.assertEqual( - self.mock_type.call_args[1]['support_auto'], False) + self.mock_type.call_args[0][-1]['support_auto'], False) def test_light(self): """Test light devices.""" @@ -120,7 +120,7 @@ def test_climate_support_auto(self): # pylint: disable=unsubscriptable-object self.assertEqual( - self.mock_type.call_args[1]['support_auto'], True) + self.mock_type.call_args[0][-1]['support_auto'], True) def test_switch(self): """Test switch.""" diff --git a/tests/components/homekit/test_type_covers.py b/tests/components/homekit/test_type_covers.py index 5ab0f06e55ba12..9a7b2ea6c6b492 100644 --- a/tests/components/homekit/test_type_covers.py +++ b/tests/components/homekit/test_type_covers.py @@ -35,7 +35,7 @@ def test_window_set_cover_position(self): """Test if accessory and HA are updated accordingly.""" window_cover = 'cover.window' - acc = WindowCovering(self.hass, 'Cover', window_cover, aid=2) + acc = WindowCovering(self.hass, 'Cover', window_cover, None, aid=2) 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 9b559f714230d1..4bc85916aacdf0 100644 --- a/tests/components/homekit/test_type_lights.py +++ b/tests/components/homekit/test_type_lights.py @@ -53,7 +53,7 @@ def test_light_basic(self): self.hass.states.set(entity_id, STATE_ON, {ATTR_SUPPORTED_FEATURES: 0}) - acc = self.light_cls(self.hass, 'Light', entity_id, aid=2) + acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) self.assertEqual(acc.aid, 2) self.assertEqual(acc.category, 5) # Lightbulb self.assertEqual(acc.char_on.value, 0) @@ -98,7 +98,7 @@ def test_light_brightness(self): self.hass.states.set(entity_id, STATE_ON, { ATTR_SUPPORTED_FEATURES: SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS: 255}) - acc = self.light_cls(self.hass, 'Light', entity_id, aid=2) + acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) self.assertEqual(acc.char_brightness.value, 0) acc.run() @@ -141,7 +141,7 @@ def test_light_color_temperature(self): self.hass.states.set(entity_id, STATE_ON, { ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR_TEMP, ATTR_COLOR_TEMP: 190}) - acc = self.light_cls(self.hass, 'Light', entity_id, aid=2) + acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) self.assertEqual(acc.char_color_temperature.value, 153) acc.run() @@ -164,7 +164,7 @@ def test_light_rgb_color(self): self.hass.states.set(entity_id, STATE_ON, { ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR, ATTR_HS_COLOR: (260, 90)}) - acc = self.light_cls(self.hass, 'Light', entity_id, aid=2) + acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) 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 23ed810954aac8..1910d7cc45709a 100644 --- a/tests/components/homekit/test_type_locks.py +++ b/tests/components/homekit/test_type_locks.py @@ -33,7 +33,7 @@ def test_lock_unlock(self): """Test if accessory and HA are updated accordingly.""" kitchen_lock = 'lock.kitchen_door' - acc = Lock(self.hass, 'Lock', kitchen_lock, aid=2) + acc = Lock(self.hass, 'Lock', kitchen_lock, None, aid=2) 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 324822ab2ace90..b0f058da9b1937 100644 --- a/tests/components/homekit/test_type_security_systems.py +++ b/tests/components/homekit/test_type_security_systems.py @@ -36,7 +36,7 @@ def test_switch_set_state(self): acp = 'alarm_control_panel.test' acc = SecuritySystem(self.hass, 'SecuritySystem', acp, - alarm_code='1234', aid=2) + {ATTR_CODE: '1234'}, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -108,7 +108,7 @@ def test_no_alarm_code(self): acp = 'alarm_control_panel.test' acc = SecuritySystem(self.hass, 'SecuritySystem', acp, - alarm_code=None, aid=2) + {ATTR_CODE: None}, aid=2) acc.run() # Set from HomeKit diff --git a/tests/components/homekit/test_type_sensors.py b/tests/components/homekit/test_type_sensors.py index b16646626e0284..2a3a8b91637ea9 100644 --- a/tests/components/homekit/test_type_sensors.py +++ b/tests/components/homekit/test_type_sensors.py @@ -26,7 +26,8 @@ def test_temperature(self): """Test if accessory is updated after state change.""" entity_id = 'sensor.temperature' - acc = TemperatureSensor(self.hass, 'Temperature', entity_id, aid=2) + acc = TemperatureSensor(self.hass, 'Temperature', entity_id, + None, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -54,7 +55,7 @@ def test_humidity(self): """Test if accessory is updated after state change.""" entity_id = 'sensor.humidity' - acc = HumiditySensor(self.hass, 'Humidity', entity_id, aid=2) + acc = HumiditySensor(self.hass, 'Humidity', entity_id, None, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -78,7 +79,7 @@ def test_binary(self): {ATTR_DEVICE_CLASS: "opening"}) self.hass.block_till_done() - acc = BinarySensor(self.hass, 'Window Opening', entity_id, aid=2) + acc = BinarySensor(self.hass, 'Window Opening', entity_id, None, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -118,6 +119,7 @@ def test_binary_device_classes(self): {ATTR_DEVICE_CLASS: device_class}) self.hass.block_till_done() - acc = BinarySensor(self.hass, 'Binary Sensor', entity_id, aid=2) + acc = BinarySensor(self.hass, 'Binary Sensor', entity_id, + None, aid=2) 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 f5a38cf9f08770..c8352d53c3efd2 100644 --- a/tests/components/homekit/test_type_switches.py +++ b/tests/components/homekit/test_type_switches.py @@ -34,7 +34,7 @@ def test_switch_set_state(self): entity_id = 'switch.test' domain = split_entity_id(entity_id)[0] - acc = Switch(self.hass, 'Switch', entity_id, aid=2) + acc = Switch(self.hass, 'Switch', entity_id, None, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -70,7 +70,7 @@ def test_remote_set_state(self): entity_id = 'remote.test' domain = split_entity_id(entity_id)[0] - acc = Switch(self.hass, 'Switch', entity_id, aid=2) + acc = Switch(self.hass, 'Switch', entity_id, None, aid=2) acc.run() self.assertEqual(acc.char_on.value, False) @@ -89,7 +89,7 @@ def test_input_boolean_set_state(self): entity_id = 'input_boolean.test' domain = split_entity_id(entity_id)[0] - acc = Switch(self.hass, 'Switch', entity_id, aid=2) + acc = Switch(self.hass, 'Switch', entity_id, None, aid=2) 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 8e5dcc5e6d0d94..6c8e42f099ac96 100644 --- a/tests/components/homekit/test_type_thermostats.py +++ b/tests/components/homekit/test_type_thermostats.py @@ -52,7 +52,8 @@ def test_default_thermostat(self): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, 'Climate', climate, False, aid=2) + acc = self.thermostat_cls(self.hass, 'Climate', climate, + {'support_auto': False}, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -187,7 +188,8 @@ def test_auto_thermostat(self): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, 'Climate', climate, True) + acc = self.thermostat_cls(self.hass, 'Climate', climate, + {'support_auto': True}, aid=2) acc.run() self.assertEqual(acc.char_cooling_thresh_temp.value, 23.0) @@ -257,7 +259,8 @@ def test_thermostat_fahrenheit(self): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, 'Climate', climate, True) + acc = self.thermostat_cls(self.hass, 'Climate', climate, + {'support_auto': True}, aid=2) acc.run() self.hass.states.set(climate, STATE_AUTO, From dfa719171f64194806a4e3578c7476c69961fa3c Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Tue, 10 Apr 2018 21:13:46 +0200 Subject: [PATCH 06/12] Thermostat: Moved feature check to type file --- homeassistant/components/homekit/__init__.py | 7 ------ .../components/homekit/type_thermostats.py | 17 +++++++++----- .../homekit/test_get_accessories.py | 8 ------- tests/components/homekit/test_type_lights.py | 4 ++++ .../homekit/test_type_thermostats.py | 22 ++++++++++++------- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index 91503b4b804349..c9fab2f857a1a1 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -8,8 +8,6 @@ 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_SUPPORTED_FEATURES, ATTR_UNIT_OF_MEASUREMENT, @@ -86,12 +84,7 @@ def get_accessory(hass, state, aid, config): a_type = 'BinarySensor' 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 a_type = 'Thermostat' - config['support_auto'] = bool(features & support_temp_range) elif state.domain == 'cover': # Only add covers that support set_cover_position diff --git a/homeassistant/components/homekit/type_thermostats.py b/homeassistant/components/homekit/type_thermostats.py index fbad0a55638fc8..71b9ec57a0788b 100644 --- a/homeassistant/components/homekit/type_thermostats.py +++ b/homeassistant/components/homekit/type_thermostats.py @@ -5,9 +5,11 @@ 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 @@ -26,6 +28,9 @@ 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): @@ -37,16 +42,18 @@ def __init__(self, hass, name, entity_id, config, **kwargs): category=CATEGORY_THERMOSTAT, **kwargs) self._unit = TEMP_CELSIUS - self._support_auto = config['support_auto'] 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 + features = self.hass.states.get(self.entity_id) \ + .attributes.get(ATTR_SUPPORTED_FEATURES) + support_auto = bool(features & SUPPORT_TEMP_RANGE) extra_chars = [ CHAR_COOLING_THRESHOLD_TEMPERATURE, - CHAR_HEATING_THRESHOLD_TEMPERATURE] if self._support_auto else None + CHAR_HEATING_THRESHOLD_TEMPERATURE] if support_auto else None # Preload the thermostat service serv_thermostat = add_preload_service(self, SERV_THERMOSTAT, @@ -76,7 +83,7 @@ def __init__(self, hass, name, entity_id, config, **kwargs): self.char_display_units.value = 0 # If the device supports it: high and low temperature characteristics - if self._support_auto: + if support_auto: self.char_cooling_thresh_temp = serv_thermostat. \ get_characteristic(CHAR_COOLING_THRESHOLD_TEMPERATURE) self.char_cooling_thresh_temp.value = 23.0 diff --git a/tests/components/homekit/test_get_accessories.py b/tests/components/homekit/test_get_accessories.py index 68ef4919b5ff09..9569d9fd0632d5 100644 --- a/tests/components/homekit/test_get_accessories.py +++ b/tests/components/homekit/test_get_accessories.py @@ -99,10 +99,6 @@ def test_climate(self): state = State('climate.test', 'auto') get_accessory(None, state, 2, {}) - # pylint: disable=unsubscriptable-object - self.assertEqual( - self.mock_type.call_args[0][-1]['support_auto'], False) - def test_light(self): """Test light devices.""" with patch.dict(TYPES, {'Light': self.mock_type}): @@ -118,10 +114,6 @@ def test_climate_support_auto(self): SUPPORT_TARGET_TEMPERATURE_HIGH}) get_accessory(None, state, 2, {}) - # pylint: disable=unsubscriptable-object - self.assertEqual( - self.mock_type.call_args[0][-1]['support_auto'], True) - def test_switch(self): """Test switch.""" with patch.dict(TYPES, {'Switch': self.mock_type}): diff --git a/tests/components/homekit/test_type_lights.py b/tests/components/homekit/test_type_lights.py index 4bc85916aacdf0..10b85c79040bf0 100644 --- a/tests/components/homekit/test_type_lights.py +++ b/tests/components/homekit/test_type_lights.py @@ -53,6 +53,7 @@ def test_light_basic(self): self.hass.states.set(entity_id, STATE_ON, {ATTR_SUPPORTED_FEATURES: 0}) + self.hass.block_till_done() acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) self.assertEqual(acc.aid, 2) self.assertEqual(acc.category, 5) # Lightbulb @@ -98,6 +99,7 @@ def test_light_brightness(self): self.hass.states.set(entity_id, STATE_ON, { ATTR_SUPPORTED_FEATURES: SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS: 255}) + self.hass.block_till_done() acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) self.assertEqual(acc.char_brightness.value, 0) @@ -141,6 +143,7 @@ def test_light_color_temperature(self): self.hass.states.set(entity_id, STATE_ON, { ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR_TEMP, ATTR_COLOR_TEMP: 190}) + self.hass.block_till_done() acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) self.assertEqual(acc.char_color_temperature.value, 153) @@ -164,6 +167,7 @@ def test_light_rgb_color(self): self.hass.states.set(entity_id, STATE_ON, { ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR, ATTR_HS_COLOR: (260, 90)}) + self.hass.block_till_done() acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) self.assertEqual(acc.char_hue.value, 0) self.assertEqual(acc.char_saturation.value, 75) diff --git a/tests/components/homekit/test_type_thermostats.py b/tests/components/homekit/test_type_thermostats.py index 6c8e42f099ac96..07ab28caeb1442 100644 --- a/tests/components/homekit/test_type_thermostats.py +++ b/tests/components/homekit/test_type_thermostats.py @@ -7,8 +7,9 @@ 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,8 +53,9 @@ def test_default_thermostat(self): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, 'Climate', climate, - {'support_auto': 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, None, aid=2) acc.run() self.assertEqual(acc.aid, 2) @@ -188,8 +190,10 @@ def test_auto_thermostat(self): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, 'Climate', climate, - {'support_auto': True}, aid=2) + # 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, None, aid=2) acc.run() self.assertEqual(acc.char_cooling_thresh_temp.value, 23.0) @@ -259,8 +263,10 @@ def test_thermostat_fahrenheit(self): """Test if accessory and HA are updated accordingly.""" climate = 'climate.test' - acc = self.thermostat_cls(self.hass, 'Climate', climate, - {'support_auto': True}, aid=2) + # 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, None, aid=2) acc.run() self.hass.states.set(climate, STATE_AUTO, From 99b67df31a1ecdc3265cb4342330c3d7bceff113 Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Tue, 10 Apr 2018 22:00:56 +0200 Subject: [PATCH 07/12] Init_setup --- .../components/homekit/accessories.py | 14 ++++++++++-- .../components/homekit/type_covers.py | 8 +++---- .../components/homekit/type_lights.py | 8 +++---- .../components/homekit/type_locks.py | 8 +++---- .../homekit/type_security_systems.py | 8 +++---- .../components/homekit/type_sensors.py | 22 +++++++++---------- .../components/homekit/type_switches.py | 8 +++---- .../components/homekit/type_thermostats.py | 8 +++---- tests/components/homekit/test_accessories.py | 7 +++--- 9 files changed, 49 insertions(+), 42 deletions(-) diff --git a/homeassistant/components/homekit/accessories.py b/homeassistant/components/homekit/accessories.py index d6e678cd6f504e..ac401f02e3d150 100644 --- a/homeassistant/components/homekit/accessories.py +++ b/homeassistant/components/homekit/accessories.py @@ -85,13 +85,23 @@ def set_accessory_info(acc, name, model, manufacturer=MANUFACTURER, class HomeAccessory(Accessory): """Adapter class for Accessory.""" - def __init__(self, hass, name, entity_id, category='OTHER', **kwargs): + category = 'OTHER' + + def __init__(self, hass, name, entity_id, config, **kwargs): """Initialize a Accessory object.""" super().__init__(name, **kwargs) set_accessory_info(self, name, model=entity_id) - self.category = getattr(Category, category, Category.OTHER) + self.category = getattr(Category, self.category, Category.OTHER) self.entity_id = entity_id self.hass = hass + self.init_setup(config) + + def init_setup(self, config): + """Method called from __init__ at instance creation. + + Overridden by accessory types. + """ + pass def _set_services(self): add_preload_service(self, SERV_ACCESSORY_INFO) diff --git a/homeassistant/components/homekit/type_covers.py b/homeassistant/components/homekit/type_covers.py index 7eb133a81ea20c..5f88ddc5ca7b65 100644 --- a/homeassistant/components/homekit/type_covers.py +++ b/homeassistant/components/homekit/type_covers.py @@ -1,4 +1,5 @@ """Class to hold all cover accessories.""" +# pylint: disable=attribute-defined-outside-init import logging from homeassistant.components.cover import ATTR_CURRENT_POSITION @@ -19,11 +20,10 @@ class WindowCovering(HomeAccessory): The cover entity must support: set_cover_position. """ - def __init__(self, hass, name, entity_id, config, **kwargs): - """Initialize a WindowCovering accessory object.""" - super().__init__(hass, name, entity_id, - category=CATEGORY_WINDOW_COVERING, **kwargs) + category = CATEGORY_WINDOW_COVERING + def init_setup(self, config): + """Initialize a WindowCovering accessory object.""" self.current_position = None self.homekit_target = None diff --git a/homeassistant/components/homekit/type_lights.py b/homeassistant/components/homekit/type_lights.py index 353f71fee0faf3..426dfc2838a565 100644 --- a/homeassistant/components/homekit/type_lights.py +++ b/homeassistant/components/homekit/type_lights.py @@ -1,4 +1,5 @@ """Class to hold all light accessories.""" +# pylint: disable=attribute-defined-outside-init import logging from homeassistant.components.light import ( @@ -24,11 +25,10 @@ class Light(HomeAccessory): Currently supports: state, brightness, color temperature, rgb_color. """ - def __init__(self, hass, name, entity_id, config, **kwargs): - """Initialize a new Light accessory object.""" - super().__init__(hass, name, entity_id, - category=CATEGORY_LIGHT, **kwargs) + category = CATEGORY_LIGHT + def init_setup(self, config): + """Initialize a new Light accessory object.""" self._flag = {CHAR_ON: False, CHAR_BRIGHTNESS: False, CHAR_HUE: False, CHAR_SATURATION: False, CHAR_COLOR_TEMPERATURE: False, RGB_COLOR: False} diff --git a/homeassistant/components/homekit/type_locks.py b/homeassistant/components/homekit/type_locks.py index d141090548ae79..a80b9f7ac66529 100644 --- a/homeassistant/components/homekit/type_locks.py +++ b/homeassistant/components/homekit/type_locks.py @@ -1,4 +1,5 @@ """Class to hold all lock accessories.""" +# pylint: disable=attribute-defined-outside-init import logging from homeassistant.components.lock import ( @@ -27,11 +28,10 @@ class Lock(HomeAccessory): The lock entity must support: unlock and lock. """ - def __init__(self, hass, name, entity_id, config, **kwargs): - """Initialize a Lock accessory object.""" - super().__init__(hass, name, entity_id, - category=CATEGORY_LOCK, **kwargs) + category = CATEGORY_LOCK + def init_setup(self, config): + """Initialize a Lock accessory object.""" self.flag_target_state = False serv_lock_mechanism = add_preload_service(self, SERV_LOCK) diff --git a/homeassistant/components/homekit/type_security_systems.py b/homeassistant/components/homekit/type_security_systems.py index ed742f3dee12fc..0649d06e1baa83 100644 --- a/homeassistant/components/homekit/type_security_systems.py +++ b/homeassistant/components/homekit/type_security_systems.py @@ -1,4 +1,5 @@ """Class to hold all alarm control panel accessories.""" +# pylint: disable=attribute-defined-outside-init import logging from homeassistant.const import ( @@ -27,11 +28,10 @@ class SecuritySystem(HomeAccessory): """Generate an SecuritySystem accessory for an alarm control panel.""" - def __init__(self, hass, name, entity_id, config, **kwargs): - """Initialize a SecuritySystem accessory object.""" - super().__init__(hass, name, entity_id, - category=CATEGORY_ALARM_SYSTEM, **kwargs) + category = CATEGORY_ALARM_SYSTEM + def init_setup(self, config): + """Initialize a SecuritySystem accessory object.""" self._alarm_code = config[ATTR_CODE] self.flag_target_state = False diff --git a/homeassistant/components/homekit/type_sensors.py b/homeassistant/components/homekit/type_sensors.py index 0e30e1809b01b2..4a393e55291f1f 100755 --- a/homeassistant/components/homekit/type_sensors.py +++ b/homeassistant/components/homekit/type_sensors.py @@ -1,4 +1,5 @@ """Class to hold all sensor accessories.""" +# pylint: disable=attribute-defined-outside-init import logging from homeassistant.const import ( @@ -41,11 +42,10 @@ class TemperatureSensor(HomeAccessory): Sensor entity must return temperature in °C, °F. """ - def __init__(self, hass, name, entity_id, config, **kwargs): - """Initialize a TemperatureSensor accessory object.""" - super().__init__(hass, name, entity_id, - category=CATEGORY_SENSOR, **kwargs) + category = CATEGORY_SENSOR + def init_setup(self, config): + """Initialize a TemperatureSensor accessory object.""" 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) @@ -67,11 +67,10 @@ def update_state(self, new_state): class HumiditySensor(HomeAccessory): """Generate a HumiditySensor accessory as humidity sensor.""" - def __init__(self, hass, name, entity_id, config, **kwargs): - """Initialize a HumiditySensor accessory object.""" - super().__init__(hass, name, entity_id, - category=CATEGORY_SENSOR, **kwargs) + category = CATEGORY_SENSOR + def init_setup(self, config): + """Initialize a HumiditySensor accessory object.""" serv_humidity = add_preload_service(self, SERV_HUMIDITY_SENSOR) self.char_humidity = serv_humidity \ .get_characteristic(CHAR_CURRENT_HUMIDITY) @@ -90,11 +89,10 @@ def update_state(self, new_state): class BinarySensor(HomeAccessory): """Generate a BinarySensor accessory as binary sensor.""" - def __init__(self, hass, name, entity_id, config, **kwargs): - """Initialize a BinarySensor accessory object.""" - super().__init__(hass, name, entity_id, - category=CATEGORY_SENSOR, **kwargs) + category = CATEGORY_SENSOR + def init_setup(self, config): + """Initialize a BinarySensor accessory object.""" device_class = self.hass.states.get(self.entity_id).attributes \ .get(ATTR_DEVICE_CLASS) service_char = BINARY_SENSOR_SERVICE_MAP[device_class] \ diff --git a/homeassistant/components/homekit/type_switches.py b/homeassistant/components/homekit/type_switches.py index 1c46f9e113ddb8..8bcbe7131e8332 100644 --- a/homeassistant/components/homekit/type_switches.py +++ b/homeassistant/components/homekit/type_switches.py @@ -1,4 +1,5 @@ """Class to hold all switch accessories.""" +# pylint: disable=attribute-defined-outside-init import logging from homeassistant.const import ( @@ -16,11 +17,10 @@ class Switch(HomeAccessory): """Generate a Switch accessory.""" - def __init__(self, hass, name, entity_id, config, **kwargs): - """Initialize a Switch accessory object to represent a remote.""" - super().__init__(hass, name, entity_id, - category=CATEGORY_SWITCH, **kwargs) + category = CATEGORY_SWITCH + def init_setup(self, config): + """Initialize a Switch accessory object to represent a remote.""" self._domain = split_entity_id(self.entity_id)[0] self.flag_target_state = False diff --git a/homeassistant/components/homekit/type_thermostats.py b/homeassistant/components/homekit/type_thermostats.py index 71b9ec57a0788b..59d6ffa0a90864 100644 --- a/homeassistant/components/homekit/type_thermostats.py +++ b/homeassistant/components/homekit/type_thermostats.py @@ -1,4 +1,5 @@ """Class to hold all thermostat accessories.""" +# pylint: disable=attribute-defined-outside-init import logging from homeassistant.components.climate import ( @@ -36,11 +37,10 @@ class Thermostat(HomeAccessory): """Generate a Thermostat accessory for a climate.""" - def __init__(self, hass, name, entity_id, config, **kwargs): - """Initialize a Thermostat accessory object.""" - super().__init__(hass, name, entity_id, - category=CATEGORY_THERMOSTAT, **kwargs) + category = CATEGORY_THERMOSTAT + def init_setup(self, config): + """Initialize a Thermostat accessory object.""" self._unit = TEMP_CELSIUS self.heat_cool_flag_target_state = False self.temperature_flag_target_state = False diff --git a/tests/components/homekit/test_accessories.py b/tests/components/homekit/test_accessories.py index a0cf37d9a3832f..733abd6bd7a480 100644 --- a/tests/components/homekit/test_accessories.py +++ b/tests/components/homekit/test_accessories.py @@ -91,7 +91,7 @@ def test_add_preload_service(self): def test_set_accessory_info(self): """Test setting the basic accessory information.""" # Test HomeAccessory - acc = HomeAccessory('hass', 'Home Accessory', 'homekit.accessory') + acc = HomeAccessory('hass', 'Home Accessory', 'homekit.accessory', {}) set_accessory_info(acc, 'name', 'model', 'manufacturer', '0000') serv = acc.get_service(SERV_ACCESSORY_INFO) @@ -117,7 +117,7 @@ def test_home_accessory(self): """Test HomeAccessory class.""" hass = get_test_home_assistant() - acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory') + acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory', {}) self.assertEqual(acc.hass, hass) self.assertEqual(acc.display_name, 'Home Accessory') self.assertEqual(acc.category, 1) # Category.OTHER @@ -132,9 +132,8 @@ def test_home_accessory(self): hass.states.set('homekit.accessory', 'off') hass.block_till_done() - acc = HomeAccessory('hass', 'test_name', 'test_model', 'FAN', aid=2) + acc = HomeAccessory('hass', 'test_name', 'test_model', {}, aid=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 From 2f7ce59e752ddaadb047713a4cacb368f8c43e58 Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Wed, 11 Apr 2018 00:32:54 +0200 Subject: [PATCH 08/12] Small changes * HomeAccessory, HomeBridge: removed **kwargs * Added defaults for a_type, config --- homeassistant/components/homekit/__init__.py | 7 +++++-- homeassistant/components/homekit/accessories.py | 8 ++++---- tests/components/homekit/test_accessories.py | 6 ++++-- tests/components/homekit/test_get_accessories.py | 2 +- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index c9fab2f857a1a1..b85b6ce6248cd8 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -77,6 +77,9 @@ def get_accessory(hass, state, aid, config): state.entity_id) return None + a_type = None + config = config or {} + if state.domain == 'alarm_control_panel': a_type = 'SecuritySystem' @@ -109,11 +112,11 @@ def get_accessory(hass, state, aid, config): or state.domain == 'input_boolean' or state.domain == 'script': a_type = 'Switch' - else: + 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, config, aid=aid) + return TYPES[a_type](hass, state.name, state.entity_id, config, aid) def generate_aid(entity_id): diff --git a/homeassistant/components/homekit/accessories.py b/homeassistant/components/homekit/accessories.py index ac401f02e3d150..f5ac59b36742df 100644 --- a/homeassistant/components/homekit/accessories.py +++ b/homeassistant/components/homekit/accessories.py @@ -87,9 +87,9 @@ class HomeAccessory(Accessory): category = 'OTHER' - def __init__(self, hass, name, entity_id, config, **kwargs): + def __init__(self, hass, name, entity_id, config, aid): """Initialize a Accessory object.""" - super().__init__(name, **kwargs) + super().__init__(name, aid=aid) set_accessory_info(self, name, model=entity_id) self.category = getattr(Category, self.category, Category.OTHER) self.entity_id = entity_id @@ -132,9 +132,9 @@ def update_state(self, new_state): class HomeBridge(Bridge): """Adapter class for Bridge.""" - def __init__(self, hass, name=BRIDGE_NAME, **kwargs): + def __init__(self, hass, name=BRIDGE_NAME): """Initialize a Bridge object.""" - super().__init__(name, **kwargs) + super().__init__(name) set_accessory_info(self, name, model=BRIDGE_MODEL) self.hass = hass diff --git a/tests/components/homekit/test_accessories.py b/tests/components/homekit/test_accessories.py index 733abd6bd7a480..6497d486c56d44 100644 --- a/tests/components/homekit/test_accessories.py +++ b/tests/components/homekit/test_accessories.py @@ -91,7 +91,8 @@ def test_add_preload_service(self): def test_set_accessory_info(self): """Test setting the basic accessory information.""" # Test HomeAccessory - acc = HomeAccessory('hass', 'Home Accessory', 'homekit.accessory', {}) + acc = HomeAccessory('hass', 'Home Accessory', 'homekit.accessory', + {}, aid=2) set_accessory_info(acc, 'name', 'model', 'manufacturer', '0000') serv = acc.get_service(SERV_ACCESSORY_INFO) @@ -117,7 +118,8 @@ def test_home_accessory(self): """Test HomeAccessory class.""" hass = get_test_home_assistant() - acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory', {}) + acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory', + {}, aid=2) self.assertEqual(acc.hass, hass) self.assertEqual(acc.display_name, 'Home Accessory') self.assertEqual(acc.category, 1) # Category.OTHER diff --git a/tests/components/homekit/test_get_accessories.py b/tests/components/homekit/test_get_accessories.py index 9569d9fd0632d5..6cb369ca5d1e79 100644 --- a/tests/components/homekit/test_get_accessories.py +++ b/tests/components/homekit/test_get_accessories.py @@ -91,7 +91,7 @@ def test_alarm_control_panel(self): # pylint: disable=unsubscriptable-object self.assertEqual( - self.mock_type.call_args[0][-1][ATTR_CODE], '1234') + self.mock_type.call_args[0][3][ATTR_CODE], '1234') def test_climate(self): """Test climate devices.""" From 279375339d007c0eff0bfbc70afc2b10a94f4c44 Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Wed, 11 Apr 2018 15:13:38 +0200 Subject: [PATCH 09/12] Use super().__init__(*args, category=CATEGORY) --- homeassistant/components/homekit/__init__.py | 2 +- homeassistant/components/homekit/accessories.py | 14 ++------------ homeassistant/components/homekit/type_covers.py | 6 ++---- homeassistant/components/homekit/type_lights.py | 6 ++---- homeassistant/components/homekit/type_locks.py | 6 ++---- .../components/homekit/type_security_systems.py | 6 ++---- homeassistant/components/homekit/type_sensors.py | 16 ++++++---------- .../components/homekit/type_switches.py | 6 ++---- .../components/homekit/type_thermostats.py | 6 ++---- tests/components/homekit/test_accessories.py | 8 +++----- tests/components/homekit/test_get_accessories.py | 7 ++++--- tests/components/homekit/test_type_covers.py | 2 +- tests/components/homekit/test_type_lights.py | 8 ++++---- tests/components/homekit/test_type_locks.py | 2 +- .../homekit/test_type_security_systems.py | 4 ++-- tests/components/homekit/test_type_sensors.py | 9 +++++---- tests/components/homekit/test_type_switches.py | 6 +++--- .../components/homekit/test_type_thermostats.py | 9 ++++++--- 18 files changed, 50 insertions(+), 73 deletions(-) diff --git a/homeassistant/components/homekit/__init__.py b/homeassistant/components/homekit/__init__.py index b85b6ce6248cd8..02d21889f6b799 100644 --- a/homeassistant/components/homekit/__init__.py +++ b/homeassistant/components/homekit/__init__.py @@ -116,7 +116,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, config, aid) + return TYPES[a_type](hass, state.name, state.entity_id, aid, config=config) def generate_aid(entity_id): diff --git a/homeassistant/components/homekit/accessories.py b/homeassistant/components/homekit/accessories.py index f5ac59b36742df..c01d0e32fcb71f 100644 --- a/homeassistant/components/homekit/accessories.py +++ b/homeassistant/components/homekit/accessories.py @@ -85,23 +85,13 @@ def set_accessory_info(acc, name, model, manufacturer=MANUFACTURER, class HomeAccessory(Accessory): """Adapter class for Accessory.""" - category = 'OTHER' - - def __init__(self, hass, name, entity_id, config, aid): + def __init__(self, hass, name, entity_id, aid, category): """Initialize a Accessory object.""" super().__init__(name, aid=aid) set_accessory_info(self, name, model=entity_id) - self.category = getattr(Category, self.category, Category.OTHER) + self.category = getattr(Category, category, Category.OTHER) self.entity_id = entity_id self.hass = hass - self.init_setup(config) - - def init_setup(self, config): - """Method called from __init__ at instance creation. - - Overridden by accessory types. - """ - pass def _set_services(self): add_preload_service(self, SERV_ACCESSORY_INFO) diff --git a/homeassistant/components/homekit/type_covers.py b/homeassistant/components/homekit/type_covers.py index 5f88ddc5ca7b65..c70b3d8c05d080 100644 --- a/homeassistant/components/homekit/type_covers.py +++ b/homeassistant/components/homekit/type_covers.py @@ -1,5 +1,4 @@ """Class to hold all cover accessories.""" -# pylint: disable=attribute-defined-outside-init import logging from homeassistant.components.cover import ATTR_CURRENT_POSITION @@ -20,10 +19,9 @@ class WindowCovering(HomeAccessory): The cover entity must support: set_cover_position. """ - category = CATEGORY_WINDOW_COVERING - - def init_setup(self, config): + def __init__(self, *args, config): """Initialize a WindowCovering accessory object.""" + super().__init__(*args, category=CATEGORY_WINDOW_COVERING) self.current_position = None self.homekit_target = None diff --git a/homeassistant/components/homekit/type_lights.py b/homeassistant/components/homekit/type_lights.py index 426dfc2838a565..11b632d8d363aa 100644 --- a/homeassistant/components/homekit/type_lights.py +++ b/homeassistant/components/homekit/type_lights.py @@ -1,5 +1,4 @@ """Class to hold all light accessories.""" -# pylint: disable=attribute-defined-outside-init import logging from homeassistant.components.light import ( @@ -25,10 +24,9 @@ class Light(HomeAccessory): Currently supports: state, brightness, color temperature, rgb_color. """ - category = CATEGORY_LIGHT - - def init_setup(self, config): + def __init__(self, *args, config): """Initialize a new Light accessory object.""" + 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} diff --git a/homeassistant/components/homekit/type_locks.py b/homeassistant/components/homekit/type_locks.py index a80b9f7ac66529..9a4a8e5f127350 100644 --- a/homeassistant/components/homekit/type_locks.py +++ b/homeassistant/components/homekit/type_locks.py @@ -1,5 +1,4 @@ """Class to hold all lock accessories.""" -# pylint: disable=attribute-defined-outside-init import logging from homeassistant.components.lock import ( @@ -28,10 +27,9 @@ class Lock(HomeAccessory): The lock entity must support: unlock and lock. """ - category = CATEGORY_LOCK - - def init_setup(self, config): + def __init__(self, *args, config): """Initialize a Lock accessory object.""" + super().__init__(*args, category=CATEGORY_LOCK) self.flag_target_state = False serv_lock_mechanism = add_preload_service(self, SERV_LOCK) diff --git a/homeassistant/components/homekit/type_security_systems.py b/homeassistant/components/homekit/type_security_systems.py index 0649d06e1baa83..864f90b5e045fa 100644 --- a/homeassistant/components/homekit/type_security_systems.py +++ b/homeassistant/components/homekit/type_security_systems.py @@ -1,5 +1,4 @@ """Class to hold all alarm control panel accessories.""" -# pylint: disable=attribute-defined-outside-init import logging from homeassistant.const import ( @@ -28,10 +27,9 @@ class SecuritySystem(HomeAccessory): """Generate an SecuritySystem accessory for an alarm control panel.""" - category = CATEGORY_ALARM_SYSTEM - - def init_setup(self, config): + def __init__(self, *args, config): """Initialize a SecuritySystem accessory object.""" + super().__init__(*args, category=CATEGORY_ALARM_SYSTEM) self._alarm_code = config[ATTR_CODE] self.flag_target_state = False diff --git a/homeassistant/components/homekit/type_sensors.py b/homeassistant/components/homekit/type_sensors.py index 4a393e55291f1f..01dc3afa3b33f9 100755 --- a/homeassistant/components/homekit/type_sensors.py +++ b/homeassistant/components/homekit/type_sensors.py @@ -1,5 +1,4 @@ """Class to hold all sensor accessories.""" -# pylint: disable=attribute-defined-outside-init import logging from homeassistant.const import ( @@ -42,10 +41,9 @@ class TemperatureSensor(HomeAccessory): Sensor entity must return temperature in °C, °F. """ - category = CATEGORY_SENSOR - - def init_setup(self, config): + def __init__(self, *args, config): """Initialize a TemperatureSensor accessory object.""" + 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) @@ -67,10 +65,9 @@ def update_state(self, new_state): class HumiditySensor(HomeAccessory): """Generate a HumiditySensor accessory as humidity sensor.""" - category = CATEGORY_SENSOR - - def init_setup(self, config): + def __init__(self, *args, config): """Initialize a HumiditySensor accessory object.""" + 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) @@ -89,10 +86,9 @@ def update_state(self, new_state): class BinarySensor(HomeAccessory): """Generate a BinarySensor accessory as binary sensor.""" - category = CATEGORY_SENSOR - - def init_setup(self, config): + def __init__(self, *args, config): """Initialize a BinarySensor accessory object.""" + 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] \ diff --git a/homeassistant/components/homekit/type_switches.py b/homeassistant/components/homekit/type_switches.py index 8bcbe7131e8332..ecddddd107badf 100644 --- a/homeassistant/components/homekit/type_switches.py +++ b/homeassistant/components/homekit/type_switches.py @@ -1,5 +1,4 @@ """Class to hold all switch accessories.""" -# pylint: disable=attribute-defined-outside-init import logging from homeassistant.const import ( @@ -17,10 +16,9 @@ class Switch(HomeAccessory): """Generate a Switch accessory.""" - category = CATEGORY_SWITCH - - def init_setup(self, config): + def __init__(self, *args, config): """Initialize a Switch accessory object to represent a remote.""" + super().__init__(*args, category=CATEGORY_SWITCH) self._domain = split_entity_id(self.entity_id)[0] self.flag_target_state = False diff --git a/homeassistant/components/homekit/type_thermostats.py b/homeassistant/components/homekit/type_thermostats.py index 59d6ffa0a90864..1f65f5d3b4f1c9 100644 --- a/homeassistant/components/homekit/type_thermostats.py +++ b/homeassistant/components/homekit/type_thermostats.py @@ -1,5 +1,4 @@ """Class to hold all thermostat accessories.""" -# pylint: disable=attribute-defined-outside-init import logging from homeassistant.components.climate import ( @@ -37,10 +36,9 @@ class Thermostat(HomeAccessory): """Generate a Thermostat accessory for a climate.""" - category = CATEGORY_THERMOSTAT - - def init_setup(self, config): + def __init__(self, *args, config): """Initialize a Thermostat accessory object.""" + super().__init__(*args, category=CATEGORY_THERMOSTAT) self._unit = TEMP_CELSIUS self.heat_cool_flag_target_state = False self.temperature_flag_target_state = False diff --git a/tests/components/homekit/test_accessories.py b/tests/components/homekit/test_accessories.py index 6497d486c56d44..f8e026483aaedf 100644 --- a/tests/components/homekit/test_accessories.py +++ b/tests/components/homekit/test_accessories.py @@ -91,8 +91,7 @@ def test_add_preload_service(self): def test_set_accessory_info(self): """Test setting the basic accessory information.""" # Test HomeAccessory - acc = HomeAccessory('hass', 'Home Accessory', 'homekit.accessory', - {}, aid=2) + acc = HomeAccessory('HA', 'Home Accessory', 'homekit.accessory', 2, '') set_accessory_info(acc, 'name', 'model', 'manufacturer', '0000') serv = acc.get_service(SERV_ACCESSORY_INFO) @@ -118,8 +117,7 @@ def test_home_accessory(self): """Test HomeAccessory class.""" hass = get_test_home_assistant() - acc = HomeAccessory(hass, 'Home Accessory', 'homekit.accessory', - {}, aid=2) + 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 @@ -134,7 +132,7 @@ def test_home_accessory(self): hass.states.set('homekit.accessory', 'off') hass.block_till_done() - acc = HomeAccessory('hass', 'test_name', 'test_model', {}, aid=2) + acc = HomeAccessory('hass', 'test_name', 'test_model', 2, '') self.assertEqual(acc.display_name, 'test_name') self.assertEqual(acc.aid, 2) self.assertEqual(len(acc.services), 1) diff --git a/tests/components/homekit/test_get_accessories.py b/tests/components/homekit/test_get_accessories.py index 6cb369ca5d1e79..6f2521fc4e5fee 100644 --- a/tests/components/homekit/test_get_accessories.py +++ b/tests/components/homekit/test_get_accessories.py @@ -19,14 +19,14 @@ 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 @@ -90,8 +90,9 @@ def test_alarm_control_panel(self): get_accessory(None, state, 2, config) # pylint: disable=unsubscriptable-object + print(self.mock_type.call_args[1]) self.assertEqual( - self.mock_type.call_args[0][3][ATTR_CODE], '1234') + self.mock_type.call_args[1]['config'][ATTR_CODE], '1234') def test_climate(self): """Test climate devices.""" diff --git a/tests/components/homekit/test_type_covers.py b/tests/components/homekit/test_type_covers.py index 9a7b2ea6c6b492..8e26ab519d12f5 100644 --- a/tests/components/homekit/test_type_covers.py +++ b/tests/components/homekit/test_type_covers.py @@ -35,7 +35,7 @@ def test_window_set_cover_position(self): """Test if accessory and HA are updated accordingly.""" window_cover = 'cover.window' - acc = WindowCovering(self.hass, 'Cover', window_cover, None, 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 10b85c79040bf0..10bf469c08df8f 100644 --- a/tests/components/homekit/test_type_lights.py +++ b/tests/components/homekit/test_type_lights.py @@ -54,7 +54,7 @@ def test_light_basic(self): self.hass.states.set(entity_id, STATE_ON, {ATTR_SUPPORTED_FEATURES: 0}) self.hass.block_till_done() - acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) + 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) @@ -100,7 +100,7 @@ def test_light_brightness(self): self.hass.states.set(entity_id, STATE_ON, { ATTR_SUPPORTED_FEATURES: SUPPORT_BRIGHTNESS, ATTR_BRIGHTNESS: 255}) self.hass.block_till_done() - acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) + acc = self.light_cls(self.hass, 'Light', entity_id, 2, config=None) self.assertEqual(acc.char_brightness.value, 0) acc.run() @@ -144,7 +144,7 @@ def test_light_color_temperature(self): ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR_TEMP, ATTR_COLOR_TEMP: 190}) self.hass.block_till_done() - acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) + acc = self.light_cls(self.hass, 'Light', entity_id, 2, config=None) self.assertEqual(acc.char_color_temperature.value, 153) acc.run() @@ -168,7 +168,7 @@ def test_light_rgb_color(self): ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR, ATTR_HS_COLOR: (260, 90)}) self.hass.block_till_done() - acc = self.light_cls(self.hass, 'Light', entity_id, None, aid=2) + 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 1910d7cc45709a..b205311606011a 100644 --- a/tests/components/homekit/test_type_locks.py +++ b/tests/components/homekit/test_type_locks.py @@ -33,7 +33,7 @@ def test_lock_unlock(self): """Test if accessory and HA are updated accordingly.""" kitchen_lock = 'lock.kitchen_door' - acc = Lock(self.hass, 'Lock', kitchen_lock, None, 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 b0f058da9b1937..ec538ce4b503ad 100644 --- a/tests/components/homekit/test_type_security_systems.py +++ b/tests/components/homekit/test_type_security_systems.py @@ -36,7 +36,7 @@ def test_switch_set_state(self): acp = 'alarm_control_panel.test' acc = SecuritySystem(self.hass, 'SecuritySystem', acp, - {ATTR_CODE: '1234'}, aid=2) + 2, config={ATTR_CODE: '1234'}) acc.run() self.assertEqual(acc.aid, 2) @@ -108,7 +108,7 @@ def test_no_alarm_code(self): acp = 'alarm_control_panel.test' acc = SecuritySystem(self.hass, 'SecuritySystem', acp, - {ATTR_CODE: None}, aid=2) + 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 2a3a8b91637ea9..f9dfb04b37c83e 100644 --- a/tests/components/homekit/test_type_sensors.py +++ b/tests/components/homekit/test_type_sensors.py @@ -27,7 +27,7 @@ def test_temperature(self): entity_id = 'sensor.temperature' acc = TemperatureSensor(self.hass, 'Temperature', entity_id, - None, aid=2) + 2, config=None) acc.run() self.assertEqual(acc.aid, 2) @@ -55,7 +55,7 @@ def test_humidity(self): """Test if accessory is updated after state change.""" entity_id = 'sensor.humidity' - acc = HumiditySensor(self.hass, 'Humidity', entity_id, None, aid=2) + acc = HumiditySensor(self.hass, 'Humidity', entity_id, 2, config=None) acc.run() self.assertEqual(acc.aid, 2) @@ -79,7 +79,8 @@ def test_binary(self): {ATTR_DEVICE_CLASS: "opening"}) self.hass.block_till_done() - acc = BinarySensor(self.hass, 'Window Opening', entity_id, None, aid=2) + acc = BinarySensor(self.hass, 'Window Opening', entity_id, + 2, config=None) acc.run() self.assertEqual(acc.aid, 2) @@ -120,6 +121,6 @@ def test_binary_device_classes(self): self.hass.block_till_done() acc = BinarySensor(self.hass, 'Binary Sensor', entity_id, - None, aid=2) + 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 c8352d53c3efd2..65b107e24cd8b2 100644 --- a/tests/components/homekit/test_type_switches.py +++ b/tests/components/homekit/test_type_switches.py @@ -34,7 +34,7 @@ def test_switch_set_state(self): entity_id = 'switch.test' domain = split_entity_id(entity_id)[0] - acc = Switch(self.hass, 'Switch', entity_id, None, aid=2) + acc = Switch(self.hass, 'Switch', entity_id, 2, config=None) acc.run() self.assertEqual(acc.aid, 2) @@ -70,7 +70,7 @@ def test_remote_set_state(self): entity_id = 'remote.test' domain = split_entity_id(entity_id)[0] - acc = Switch(self.hass, 'Switch', entity_id, None, 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 @@ def test_input_boolean_set_state(self): entity_id = 'input_boolean.test' domain = split_entity_id(entity_id)[0] - acc = Switch(self.hass, 'Switch', entity_id, None, 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 07ab28caeb1442..adc3fb018f8c82 100644 --- a/tests/components/homekit/test_type_thermostats.py +++ b/tests/components/homekit/test_type_thermostats.py @@ -55,7 +55,8 @@ def test_default_thermostat(self): self.hass.states.set(climate, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 0}) self.hass.block_till_done() - acc = self.thermostat_cls(self.hass, 'Climate', climate, None, aid=2) + acc = self.thermostat_cls(self.hass, 'Climate', climate, + 2, config=None) acc.run() self.assertEqual(acc.aid, 2) @@ -193,7 +194,8 @@ def test_auto_thermostat(self): # 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, None, aid=2) + acc = self.thermostat_cls(self.hass, 'Climate', climate, + 2, config=None) acc.run() self.assertEqual(acc.char_cooling_thresh_temp.value, 23.0) @@ -266,7 +268,8 @@ def test_thermostat_fahrenheit(self): # 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, None, aid=2) + acc = self.thermostat_cls(self.hass, 'Climate', climate, + 2, config=None) acc.run() self.hass.states.set(climate, STATE_AUTO, From d99f9df3a74906d175d2d72a232311e75872eecf Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Wed, 11 Apr 2018 16:02:51 +0200 Subject: [PATCH 10/12] Fix light set_color_temperature call --- homeassistant/components/homekit/type_lights.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/homekit/type_lights.py b/homeassistant/components/homekit/type_lights.py index 11b632d8d363aa..eeb8e16eb6f735 100644 --- a/homeassistant/components/homekit/type_lights.py +++ b/homeassistant/components/homekit/type_lights.py @@ -156,7 +156,8 @@ def update_state(self, new_state): 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 From 0af42de025e0f151b6f1f5d486663e1ba1833955 Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Wed, 11 Apr 2018 16:00:23 +0200 Subject: [PATCH 11/12] Added setup_char helper function --- .../components/homekit/accessories.py | 16 +++++- .../components/homekit/type_covers.py | 20 +++---- .../components/homekit/type_lights.py | 38 ++++++------- .../components/homekit/type_locks.py | 17 +++--- .../homekit/type_security_systems.py | 15 ++--- .../components/homekit/type_sensors.py | 16 +++--- .../components/homekit/type_switches.py | 7 +-- .../components/homekit/type_thermostats.py | 55 ++++++++----------- 8 files changed, 84 insertions(+), 100 deletions(-) diff --git a/homeassistant/components/homekit/accessories.py b/homeassistant/components/homekit/accessories.py index c01d0e32fcb71f..d9b90a77d68de8 100644 --- a/homeassistant/components/homekit/accessories.py +++ b/homeassistant/components/homekit/accessories.py @@ -7,7 +7,7 @@ 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 @@ -24,7 +24,7 @@ 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.""" diff --git a/homeassistant/components/homekit/type_covers.py b/homeassistant/components/homekit/type_covers.py index c70b3d8c05d080..7c7ab3e3683b3c 100644 --- a/homeassistant/components/homekit/type_covers.py +++ b/homeassistant/components/homekit/type_covers.py @@ -4,7 +4,7 @@ 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) @@ -26,17 +26,13 @@ def __init__(self, *args, config): 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.""" diff --git a/homeassistant/components/homekit/type_lights.py b/homeassistant/components/homekit/type_lights.py index eeb8e16eb6f735..9a7bce76fbacd8 100644 --- a/homeassistant/components/homekit/type_lights.py +++ b/homeassistant/components/homekit/type_lights.py @@ -7,7 +7,8 @@ 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) @@ -46,36 +47,29 @@ def __init__(self, *args, config): 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.""" diff --git a/homeassistant/components/homekit/type_locks.py b/homeassistant/components/homekit/type_locks.py index 9a4a8e5f127350..f34fc6c6a7ff0b 100644 --- a/homeassistant/components/homekit/type_locks.py +++ b/homeassistant/components/homekit/type_locks.py @@ -5,7 +5,7 @@ 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) @@ -33,15 +33,12 @@ def __init__(self, *args, config): 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.""" diff --git a/homeassistant/components/homekit/type_security_systems.py b/homeassistant/components/homekit/type_security_systems.py index 864f90b5e045fa..6b8457a3aa54bb 100644 --- a/homeassistant/components/homekit/type_security_systems.py +++ b/homeassistant/components/homekit/type_security_systems.py @@ -7,7 +7,7 @@ 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) @@ -34,14 +34,11 @@ def __init__(self, *args, config): 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.""" diff --git a/homeassistant/components/homekit/type_sensors.py b/homeassistant/components/homekit/type_sensors.py index 01dc3afa3b33f9..790f0de61033eb 100755 --- a/homeassistant/components/homekit/type_sensors.py +++ b/homeassistant/components/homekit/type_sensors.py @@ -6,7 +6,7 @@ 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, @@ -45,9 +45,9 @@ def __init__(self, *args, config): """Initialize a TemperatureSensor accessory object.""" 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, new_state): @@ -69,9 +69,8 @@ def __init__(self, *args, config): """Initialize a HumiditySensor accessory object.""" 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, new_state): """Update accessory after state change.""" @@ -96,8 +95,7 @@ def __init__(self, *args, config): 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, new_state): """Update accessory after state change.""" diff --git a/homeassistant/components/homekit/type_switches.py b/homeassistant/components/homekit/type_switches.py index ecddddd107badf..aaf13e4ea7e962 100644 --- a/homeassistant/components/homekit/type_switches.py +++ b/homeassistant/components/homekit/type_switches.py @@ -6,7 +6,7 @@ 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__) @@ -23,9 +23,8 @@ def __init__(self, *args, config): 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.""" diff --git a/homeassistant/components/homekit/type_thermostats.py b/homeassistant/components/homekit/type_thermostats.py index 1f65f5d3b4f1c9..168a5aa9711ab8 100644 --- a/homeassistant/components/homekit/type_thermostats.py +++ b/homeassistant/components/homekit/type_thermostats.py @@ -12,7 +12,8 @@ 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, @@ -58,44 +59,34 @@ def __init__(self, *args, config): extra_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 + self.char_cooling_thresh_temp = None + self.char_heating_thresh_temp = None 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 = setup_char( + CHAR_COOLING_THRESHOLD_TEMPERATURE, serv_thermostat, + value=23.0, callback=self.set_cooling_threshold) + + 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.""" From e0eabb1615f90c0c13bdca69958452c0a46006ae Mon Sep 17 00:00:00 2001 From: cdce8p <30130371+cdce8p@users.noreply.github.com> Date: Wed, 11 Apr 2018 16:10:02 +0200 Subject: [PATCH 12/12] Improved type_thermostat optional chars --- .../components/homekit/type_thermostats.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/homekit/type_thermostats.py b/homeassistant/components/homekit/type_thermostats.py index 168a5aa9711ab8..ce10b96c51c9e1 100644 --- a/homeassistant/components/homekit/type_thermostats.py +++ b/homeassistant/components/homekit/type_thermostats.py @@ -47,16 +47,15 @@ def __init__(self, *args, config): self.heatingthresh_flag_target_state = False # Add additional characteristics if auto mode is supported + self.chars = [] features = self.hass.states.get(self.entity_id) \ .attributes.get(ATTR_SUPPORTED_FEATURES) - support_auto = bool(features & SUPPORT_TEMP_RANGE) - extra_chars = [ - CHAR_COOLING_THRESHOLD_TEMPERATURE, - CHAR_HEATING_THRESHOLD_TEMPERATURE] if support_auto else None + 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 = setup_char( @@ -79,11 +78,11 @@ def __init__(self, *args, config): # If the device supports it: high and low temperature characteristics self.char_cooling_thresh_temp = None self.char_heating_thresh_temp = None - if support_auto: + 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)