diff --git a/homeassistant/components/homekit_controller/__init__.py b/homeassistant/components/homekit_controller/__init__.py
index 17cff702b70f5b4ad66a727c109a001deef3a379..2c59f062bcc603a1cb0249869b3ac82569dc2925 100644
--- a/homeassistant/components/homekit_controller/__init__.py
+++ b/homeassistant/components/homekit_controller/__init__.py
@@ -68,6 +68,11 @@ def get_serial(accessory):
     return None
 
 
+def escape_characteristic_name(char_name):
+    """Escape any dash or dots in a characteristics name."""
+    return char_name.replace('-', '_').replace('.', '_')
+
+
 class HKDevice():
     """HomeKit device."""
 
@@ -193,6 +198,57 @@ class HomeKitEntity(Entity):
         self._address = "homekit-{}-{}".format(devinfo['serial'], self._iid)
         self._features = 0
         self._chars = {}
+        self.setup()
+
+    def setup(self):
+        """Configure an entity baed on its HomeKit characterstics metadata."""
+        # pylint: disable=import-error
+        from homekit.model.characteristics import CharacteristicsTypes
+
+        pairing_data = self._accessory.pairing.pairing_data
+
+        get_uuid = CharacteristicsTypes.get_uuid
+        characteristic_types = [
+            get_uuid(c) for c in self.get_characteristic_types()
+        ]
+
+        self._chars_to_poll = []
+        self._chars = {}
+        self._char_names = {}
+
+        for accessory in pairing_data.get('accessories', []):
+            if accessory['aid'] != self._aid:
+                continue
+            for service in accessory['services']:
+                if service['iid'] != self._iid:
+                    continue
+                for char in service['characteristics']:
+                    uuid = CharacteristicsTypes.get_uuid(char['type'])
+                    if uuid not in characteristic_types:
+                        continue
+                    self._setup_characteristic(char)
+
+    def _setup_characteristic(self, char):
+        """Configure an entity based on a HomeKit characteristics metadata."""
+        # pylint: disable=import-error
+        from homekit.model.characteristics import CharacteristicsTypes
+
+        # Build up a list of (aid, iid) tuples to poll on update()
+        self._chars_to_poll.append((self._aid, char['iid']))
+
+        # Build a map of ctype -> iid
+        short_name = CharacteristicsTypes.get_short(char['type'])
+        self._chars[short_name] = char['iid']
+        self._char_names[char['iid']] = short_name
+
+        # Callback to allow entity to configure itself based on this
+        # characteristics metadata (valid values, value ranges, features, etc)
+        setup_fn_name = escape_characteristic_name(short_name)
+        setup_fn = getattr(self, '_setup_{}'.format(setup_fn_name), None)
+        if not setup_fn:
+            return
+        # pylint: disable=E1102
+        setup_fn(char)
 
     def update(self):
         """Obtain a HomeKit device's state."""
@@ -228,6 +284,10 @@ class HomeKitEntity(Entity):
         """Return True if entity is available."""
         return self._accessory.pairing is not None
 
+    def get_characteristic_types(self):
+        """Define the homekit characteristics the entity cares about."""
+        raise NotImplementedError
+
     def update_characteristics(self, characteristics):
         """Synchronise a HomeKit device state with Home Assistant."""
         raise NotImplementedError
diff --git a/homeassistant/components/homekit_controller/alarm_control_panel.py b/homeassistant/components/homekit_controller/alarm_control_panel.py
index cc760a851cfe023ade01e4326eea245f0eb88705..984be8e0c3baa3ea3f9b3dab829497d1156d847c 100644
--- a/homeassistant/components/homekit_controller/alarm_control_panel.py
+++ b/homeassistant/components/homekit_controller/alarm_control_panel.py
@@ -54,6 +54,16 @@ class HomeKitAlarmControlPanel(HomeKitEntity, AlarmControlPanel):
         self._state = None
         self._battery_level = None
 
+    def get_characteristic_types(self):
+        """Define the homekit characteristics the entity cares about."""
+        # pylint: disable=import-error
+        from homekit.model.characteristics import CharacteristicsTypes
+        return [
+            CharacteristicsTypes.SECURITY_SYSTEM_STATE_CURRENT,
+            CharacteristicsTypes.SECURITY_SYSTEM_STATE_TARGET,
+            CharacteristicsTypes.BATTERY_LEVEL,
+        ]
+
     def update_characteristics(self, characteristics):
         """Synchronise the Alarm Control Panel state with Home Assistant."""
         # pylint: disable=import-error
@@ -63,14 +73,8 @@ class HomeKitAlarmControlPanel(HomeKitEntity, AlarmControlPanel):
             ctype = characteristic['type']
             ctype = CharacteristicsTypes.get_short(ctype)
             if ctype == "security-system-state.current":
-                self._chars['security-system-state.current'] = \
-                    characteristic['iid']
                 self._state = CURRENT_STATE_MAP[characteristic['value']]
-            elif ctype == "security-system-state.target":
-                self._chars['security-system-state.target'] = \
-                    characteristic['iid']
             elif ctype == "battery-level":
-                self._chars['battery-level'] = characteristic['iid']
                 self._battery_level = characteristic['value']
 
     @property
diff --git a/homeassistant/components/homekit_controller/climate.py b/homeassistant/components/homekit_controller/climate.py
index 484c064d53db3b0d4731ee5616cf13a7d670d7d6..042a499c55adb6127ca7d10d565630160e5c52b4 100644
--- a/homeassistant/components/homekit_controller/climate.py
+++ b/homeassistant/components/homekit_controller/climate.py
@@ -49,6 +49,29 @@ class HomeKitClimateDevice(HomeKitEntity, ClimateDevice):
         self._current_temp = None
         self._target_temp = None
 
+    def get_characteristic_types(self):
+        """Define the homekit characteristics the entity cares about."""
+        # pylint: disable=import-error
+        from homekit.model.characteristics import CharacteristicsTypes
+        return [
+            CharacteristicsTypes.HEATING_COOLING_CURRENT,
+            CharacteristicsTypes.HEATING_COOLING_TARGET,
+            CharacteristicsTypes.TEMPERATURE_CURRENT,
+            CharacteristicsTypes.TEMPERATURE_TARGET,
+        ]
+
+    def _setup_heating_cooling_target(self, characteristic):
+        self._features |= SUPPORT_OPERATION_MODE
+
+        valid_values = characteristic.get(
+            'valid-values', DEFAULT_VALID_MODES)
+        self._valid_modes = [
+            MODE_HOMEKIT_TO_HASS.get(mode) for mode in valid_values
+        ]
+
+    def _setup_temperature_target(self, characteristic):
+        self._features |= SUPPORT_TARGET_TEMPERATURE
+
     def update_characteristics(self, characteristics):
         """Synchronise device state with Home Assistant."""
         # pylint: disable=import-error
@@ -60,20 +83,11 @@ class HomeKitClimateDevice(HomeKitEntity, ClimateDevice):
                 self._state = MODE_HOMEKIT_TO_HASS.get(
                     characteristic['value'])
             if ctype == CharacteristicsTypes.HEATING_COOLING_TARGET:
-                self._chars['target_mode'] = characteristic['iid']
-                self._features |= SUPPORT_OPERATION_MODE
                 self._current_mode = MODE_HOMEKIT_TO_HASS.get(
                     characteristic['value'])
-
-                valid_values = characteristic.get(
-                    'valid-values', DEFAULT_VALID_MODES)
-                self._valid_modes = [MODE_HOMEKIT_TO_HASS.get(
-                    mode) for mode in valid_values]
             elif ctype == CharacteristicsTypes.TEMPERATURE_CURRENT:
                 self._current_temp = characteristic['value']
             elif ctype == CharacteristicsTypes.TEMPERATURE_TARGET:
-                self._chars['target_temp'] = characteristic['iid']
-                self._features |= SUPPORT_TARGET_TEMPERATURE
                 self._target_temp = characteristic['value']
 
     def set_temperature(self, **kwargs):
@@ -81,14 +95,14 @@ class HomeKitClimateDevice(HomeKitEntity, ClimateDevice):
         temp = kwargs.get(ATTR_TEMPERATURE)
 
         characteristics = [{'aid': self._aid,
-                            'iid': self._chars['target_temp'],
+                            'iid': self._chars['temperature.target'],
                             'value': temp}]
         self.put_characteristics(characteristics)
 
     def set_operation_mode(self, operation_mode):
         """Set new target operation mode."""
         characteristics = [{'aid': self._aid,
-                            'iid': self._chars['target_mode'],
+                            'iid': self._chars['heating-cooling.target'],
                             'value': MODE_HASS_TO_HOMEKIT[operation_mode]}]
         self.put_characteristics(characteristics)
 
diff --git a/homeassistant/components/homekit_controller/cover.py b/homeassistant/components/homekit_controller/cover.py
index cf9857edc0a1af16b7d57b2ec6d6f2888f160139..f9cc2ce435b0da633a413c2bfed8a0cedf20f13f 100644
--- a/homeassistant/components/homekit_controller/cover.py
+++ b/homeassistant/components/homekit_controller/cover.py
@@ -62,7 +62,6 @@ class HomeKitGarageDoorCover(HomeKitEntity, CoverDevice):
     def __init__(self, accessory, discovery_info):
         """Initialise the Cover."""
         super().__init__(accessory, discovery_info)
-        self._name = None
         self._state = None
         self._obstruction_detected = None
         self.lock_state = None
@@ -72,6 +71,20 @@ class HomeKitGarageDoorCover(HomeKitEntity, CoverDevice):
         """Define this cover as a garage door."""
         return 'garage'
 
+    def get_characteristic_types(self):
+        """Define the homekit characteristics the entity cares about."""
+        # pylint: disable=import-error
+        from homekit.model.characteristics import CharacteristicsTypes
+        return [
+            CharacteristicsTypes.DOOR_STATE_CURRENT,
+            CharacteristicsTypes.DOOR_STATE_TARGET,
+            CharacteristicsTypes.OBSTRUCTION_DETECTED,
+            CharacteristicsTypes.NAME,
+        ]
+
+    def _setup_name(self, char):
+        self._name = char['value']
+
     def update_characteristics(self, characteristics):
         """Synchronise the Cover state with Home Assistant."""
         # pylint: disable=import-error
@@ -81,18 +94,9 @@ class HomeKitGarageDoorCover(HomeKitEntity, CoverDevice):
             ctype = characteristic['type']
             ctype = CharacteristicsTypes.get_short(ctype)
             if ctype == "door-state.current":
-                self._chars['door-state.current'] = \
-                    characteristic['iid']
                 self._state = CURRENT_GARAGE_STATE_MAP[characteristic['value']]
-            elif ctype == "door-state.target":
-                self._chars['door-state.target'] = \
-                    characteristic['iid']
             elif ctype == "obstruction-detected":
-                self._chars['obstruction-detected'] = characteristic['iid']
                 self._obstruction_detected = characteristic['value']
-            elif ctype == "name":
-                self._chars['name'] = characteristic['iid']
-                self._name = characteristic['value']
 
     @property
     def available(self):
@@ -151,7 +155,6 @@ class HomeKitWindowCover(HomeKitEntity, CoverDevice):
     def __init__(self, accessory, discovery_info):
         """Initialise the Cover."""
         super().__init__(accessory, discovery_info)
-        self._name = None
         self._state = None
         self._position = None
         self._tilt_position = None
@@ -164,6 +167,26 @@ class HomeKitWindowCover(HomeKitEntity, CoverDevice):
         """Return True if entity is available."""
         return self._state is not None
 
+    def get_characteristic_types(self):
+        """Define the homekit characteristics the entity cares about."""
+        # pylint: disable=import-error
+        from homekit.model.characteristics import CharacteristicsTypes
+        return [
+            CharacteristicsTypes.POSITION_STATE,
+            CharacteristicsTypes.POSITION_CURRENT,
+            CharacteristicsTypes.POSITION_TARGET,
+            CharacteristicsTypes.POSITION_HOLD,
+            CharacteristicsTypes.VERTICAL_TILT_CURRENT,
+            CharacteristicsTypes.VERTICAL_TILT_TARGET,
+            CharacteristicsTypes.HORIZONTAL_TILT_CURRENT,
+            CharacteristicsTypes.HORIZONTAL_TILT_TARGET,
+            CharacteristicsTypes.OBSTRUCTION_DETECTED,
+            CharacteristicsTypes.NAME,
+        ]
+
+    def _setup_name(self, char):
+        self._name = char['value']
+
     def update_characteristics(self, characteristics):
         """Synchronise the Cover state with Home Assistant."""
         # pylint: disable=import-error
@@ -173,43 +196,22 @@ class HomeKitWindowCover(HomeKitEntity, CoverDevice):
             ctype = characteristic['type']
             ctype = CharacteristicsTypes.get_short(ctype)
             if ctype == "position.state":
-                self._chars['position.state'] = \
-                    characteristic['iid']
                 if 'value' in characteristic:
                     self._state = \
                         CURRENT_WINDOW_STATE_MAP[characteristic['value']]
             elif ctype == "position.current":
-                self._chars['position.current'] = \
-                    characteristic['iid']
                 self._position = characteristic['value']
-            elif ctype == "position.target":
-                self._chars['position.target'] = \
-                    characteristic['iid']
             elif ctype == "position.hold":
-                self._chars['position.hold'] = characteristic['iid']
                 if 'value' in characteristic:
                     self._hold = characteristic['value']
             elif ctype == "vertical-tilt.current":
-                self._chars['vertical-tilt.current'] = characteristic['iid']
                 if characteristic['value'] is not None:
                     self._tilt_position = characteristic['value']
             elif ctype == "horizontal-tilt.current":
-                self._chars['horizontal-tilt.current'] = characteristic['iid']
                 if characteristic['value'] is not None:
                     self._tilt_position = characteristic['value']
-            elif ctype == "vertical-tilt.target":
-                self._chars['vertical-tilt.target'] = \
-                    characteristic['iid']
-            elif ctype == "horizontal-tilt.target":
-                self._chars['horizontal-tilt.target'] = \
-                    characteristic['iid']
             elif ctype == "obstruction-detected":
-                self._chars['obstruction-detected'] = characteristic['iid']
                 self._obstruction_detected = characteristic['value']
-            elif ctype == "name":
-                self._chars['name'] = characteristic['iid']
-                if 'value' in characteristic:
-                    self._name = characteristic['value']
 
     @property
     def supported_features(self):
diff --git a/homeassistant/components/homekit_controller/light.py b/homeassistant/components/homekit_controller/light.py
index ef0ffa057fdacf6e2d9ddff9c34bce3e6446cd83..940e3782379d6755b6a59ffd51d57ee5b105802b 100644
--- a/homeassistant/components/homekit_controller/light.py
+++ b/homeassistant/components/homekit_controller/light.py
@@ -36,6 +36,30 @@ class HomeKitLight(HomeKitEntity, Light):
         self._hue = None
         self._saturation = None
 
+    def get_characteristic_types(self):
+        """Define the homekit characteristics the entity cares about."""
+        # pylint: disable=import-error
+        from homekit.model.characteristics import CharacteristicsTypes
+        return [
+            CharacteristicsTypes.ON,
+            CharacteristicsTypes.BRIGHTNESS,
+            CharacteristicsTypes.COLOR_TEMPERATURE,
+            CharacteristicsTypes.HUE,
+            CharacteristicsTypes.SATURATION,
+        ]
+
+    def _setup_brightness(self, char):
+        self._features |= SUPPORT_BRIGHTNESS
+
+    def _setup_color_temperature(self, char):
+        self._features |= SUPPORT_COLOR_TEMP
+
+    def _setup_hue(self, char):
+        self._features |= SUPPORT_COLOR
+
+    def _setup_saturation(self, char):
+        self._features |= SUPPORT_COLOR
+
     def update_characteristics(self, characteristics):
         """Synchronise light state with Home Assistant."""
         # pylint: disable=import-error
@@ -45,23 +69,14 @@ class HomeKitLight(HomeKitEntity, Light):
             ctype = characteristic['type']
             ctype = CharacteristicsTypes.get_short(ctype)
             if ctype == "on":
-                self._chars['on'] = characteristic['iid']
                 self._on = characteristic['value']
             elif ctype == 'brightness':
-                self._chars['brightness'] = characteristic['iid']
-                self._features |= SUPPORT_BRIGHTNESS
                 self._brightness = characteristic['value']
             elif ctype == 'color-temperature':
-                self._chars['color-temperature'] = characteristic['iid']
-                self._features |= SUPPORT_COLOR_TEMP
                 self._color_temperature = characteristic['value']
             elif ctype == "hue":
-                self._chars['hue'] = characteristic['iid']
-                self._features |= SUPPORT_COLOR
                 self._hue = characteristic['value']
             elif ctype == "saturation":
-                self._chars['saturation'] = characteristic['iid']
-                self._features |= SUPPORT_COLOR
                 self._saturation = characteristic['value']
 
     @property
diff --git a/homeassistant/components/homekit_controller/lock.py b/homeassistant/components/homekit_controller/lock.py
index 910567ed182f21e8d2b55a08791d4b6a5f8f90bb..53c94317c699e26a6c3f8c1db8f1e4d82b77725d 100644
--- a/homeassistant/components/homekit_controller/lock.py
+++ b/homeassistant/components/homekit_controller/lock.py
@@ -51,6 +51,16 @@ class HomeKitLock(HomeKitEntity, LockDevice):
         self._name = discovery_info['model']
         self._battery_level = None
 
+    def get_characteristic_types(self):
+        """Define the homekit characteristics the entity cares about."""
+        # pylint: disable=import-error
+        from homekit.model.characteristics import CharacteristicsTypes
+        return [
+            CharacteristicsTypes.LOCK_MECHANISM_CURRENT_STATE,
+            CharacteristicsTypes.LOCK_MECHANISM_TARGET_STATE,
+            CharacteristicsTypes.BATTERY_LEVEL,
+        ]
+
     def update_characteristics(self, characteristics):
         """Synchronise the Lock state with Home Assistant."""
         # pylint: disable=import-error
@@ -60,14 +70,8 @@ class HomeKitLock(HomeKitEntity, LockDevice):
             ctype = characteristic['type']
             ctype = CharacteristicsTypes.get_short(ctype)
             if ctype == "lock-mechanism.current-state":
-                self._chars['lock-mechanism.current-state'] = \
-                    characteristic['iid']
                 self._state = CURRENT_STATE_MAP[characteristic['value']]
-            elif ctype == "lock-mechanism.target-state":
-                self._chars['lock-mechanism.target-state'] = \
-                    characteristic['iid']
             elif ctype == "battery-level":
-                self._chars['battery-level'] = characteristic['iid']
                 self._battery_level = characteristic['value']
 
     @property
diff --git a/homeassistant/components/homekit_controller/switch.py b/homeassistant/components/homekit_controller/switch.py
index 51a71163badeeb557b19ea425cf33a512707a7a6..4bee51803f3c6667851725bc62cad9bbe0eb5881 100644
--- a/homeassistant/components/homekit_controller/switch.py
+++ b/homeassistant/components/homekit_controller/switch.py
@@ -33,6 +33,15 @@ class HomeKitSwitch(HomeKitEntity, SwitchDevice):
         self._on = None
         self._outlet_in_use = None
 
+    def get_characteristic_types(self):
+        """Define the homekit characteristics the entity cares about."""
+        # pylint: disable=import-error
+        from homekit.model.characteristics import CharacteristicsTypes
+        return [
+            CharacteristicsTypes.ON,
+            CharacteristicsTypes.OUTLET_IN_USE,
+        ]
+
     def update_characteristics(self, characteristics):
         """Synchronise the switch state with Home Assistant."""
         # pylint: disable=import-error
@@ -42,10 +51,8 @@ class HomeKitSwitch(HomeKitEntity, SwitchDevice):
             ctype = characteristic['type']
             ctype = CharacteristicsTypes.get_short(ctype)
             if ctype == "on":
-                self._chars['on'] = characteristic['iid']
                 self._on = characteristic['value']
             elif ctype == "outlet-in-use":
-                self._chars['outlet-in-use'] = characteristic['iid']
                 self._outlet_in_use = characteristic['value']
 
     @property
diff --git a/tests/components/homekit_controller/common.py b/tests/components/homekit_controller/common.py
index 8bb69e184500dc9a0d83c5abf1982dd1eb1709b0..d3c1f9ab07b8451dc40b5d016c8dd5991c7b1b5e 100644
--- a/tests/components/homekit_controller/common.py
+++ b/tests/components/homekit_controller/common.py
@@ -8,7 +8,7 @@ from homekit.model.characteristics import (
 from homekit.model import Accessory, get_id
 
 from homeassistant.components.homekit_controller import (
-    DOMAIN, HOMEKIT_ACCESSORY_DISPATCH, SERVICE_HOMEKIT, HomeKitEntity)
+    DOMAIN, HOMEKIT_ACCESSORY_DISPATCH, SERVICE_HOMEKIT)
 from homeassistant.setup import async_setup_component
 import homeassistant.util.dt as dt_util
 from tests.common import async_fire_time_changed, fire_service_discovered
@@ -168,8 +168,7 @@ async def setup_test_component(hass, services):
         }
     }
 
-    with mock.patch.object(HomeKitEntity, 'name', 'testdevice'):
-        fire_service_discovered(hass, SERVICE_HOMEKIT, discovery_info)
-        await hass.async_block_till_done()
+    fire_service_discovered(hass, SERVICE_HOMEKIT, discovery_info)
+    await hass.async_block_till_done()
 
     return Helper(hass, '.'.join((domain, 'testdevice')), pairing, accessory)
diff --git a/tests/components/homekit_controller/test_cover.py b/tests/components/homekit_controller/test_cover.py
index 4a0c244492e24d6c8c249204b6a8a0c26f002ca6..062ecc540419d3ab9e3916ddf289b42af3026201 100644
--- a/tests/components/homekit_controller/test_cover.py
+++ b/tests/components/homekit_controller/test_cover.py
@@ -39,7 +39,7 @@ def create_window_covering_service():
     obstruction.value = False
 
     name = service.add_characteristic('name')
-    name.value = "Window Cover 1"
+    name.value = "testdevice"
 
     return service
 
@@ -166,7 +166,7 @@ def create_garage_door_opener_service():
     obstruction.value = False
 
     name = service.add_characteristic('name')
-    name.value = "Garage Door Opener 1"
+    name.value = "testdevice"
 
     return service