Homekit controller BLE groundwork (#20538)
* Define the characteristics to poll (or subscribe to) up front * Configure characteristics immediately instead of during first poll * Do as much cover configuration upfront as possible * Remove test workaround as no longer needed * Remove switch code that is already handled by HomeKitEntity * Remove lock code already handled by HomeKitEntity * Remove light code already handled by HomeKitEntity * Remove alarm code already handled by HomeKitEntity * Remove climate code already handled by HomeKitEntity
This commit is contained in:
parent
995758b8ac
commit
41c1997b88
9 changed files with 177 additions and 72 deletions
|
@ -68,6 +68,11 @@ def get_serial(accessory):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def escape_characteristic_name(char_name):
|
||||||
|
"""Escape any dash or dots in a characteristics name."""
|
||||||
|
return char_name.replace('-', '_').replace('.', '_')
|
||||||
|
|
||||||
|
|
||||||
class HKDevice():
|
class HKDevice():
|
||||||
"""HomeKit device."""
|
"""HomeKit device."""
|
||||||
|
|
||||||
|
@ -193,6 +198,57 @@ class HomeKitEntity(Entity):
|
||||||
self._address = "homekit-{}-{}".format(devinfo['serial'], self._iid)
|
self._address = "homekit-{}-{}".format(devinfo['serial'], self._iid)
|
||||||
self._features = 0
|
self._features = 0
|
||||||
self._chars = {}
|
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):
|
def update(self):
|
||||||
"""Obtain a HomeKit device's state."""
|
"""Obtain a HomeKit device's state."""
|
||||||
|
@ -228,6 +284,10 @@ class HomeKitEntity(Entity):
|
||||||
"""Return True if entity is available."""
|
"""Return True if entity is available."""
|
||||||
return self._accessory.pairing is not None
|
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):
|
def update_characteristics(self, characteristics):
|
||||||
"""Synchronise a HomeKit device state with Home Assistant."""
|
"""Synchronise a HomeKit device state with Home Assistant."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
|
@ -54,6 +54,16 @@ class HomeKitAlarmControlPanel(HomeKitEntity, AlarmControlPanel):
|
||||||
self._state = None
|
self._state = None
|
||||||
self._battery_level = 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):
|
def update_characteristics(self, characteristics):
|
||||||
"""Synchronise the Alarm Control Panel state with Home Assistant."""
|
"""Synchronise the Alarm Control Panel state with Home Assistant."""
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
|
@ -63,14 +73,8 @@ class HomeKitAlarmControlPanel(HomeKitEntity, AlarmControlPanel):
|
||||||
ctype = characteristic['type']
|
ctype = characteristic['type']
|
||||||
ctype = CharacteristicsTypes.get_short(ctype)
|
ctype = CharacteristicsTypes.get_short(ctype)
|
||||||
if ctype == "security-system-state.current":
|
if ctype == "security-system-state.current":
|
||||||
self._chars['security-system-state.current'] = \
|
|
||||||
characteristic['iid']
|
|
||||||
self._state = CURRENT_STATE_MAP[characteristic['value']]
|
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":
|
elif ctype == "battery-level":
|
||||||
self._chars['battery-level'] = characteristic['iid']
|
|
||||||
self._battery_level = characteristic['value']
|
self._battery_level = characteristic['value']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -49,6 +49,29 @@ class HomeKitClimateDevice(HomeKitEntity, ClimateDevice):
|
||||||
self._current_temp = None
|
self._current_temp = None
|
||||||
self._target_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):
|
def update_characteristics(self, characteristics):
|
||||||
"""Synchronise device state with Home Assistant."""
|
"""Synchronise device state with Home Assistant."""
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
|
@ -60,20 +83,11 @@ class HomeKitClimateDevice(HomeKitEntity, ClimateDevice):
|
||||||
self._state = MODE_HOMEKIT_TO_HASS.get(
|
self._state = MODE_HOMEKIT_TO_HASS.get(
|
||||||
characteristic['value'])
|
characteristic['value'])
|
||||||
if ctype == CharacteristicsTypes.HEATING_COOLING_TARGET:
|
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(
|
self._current_mode = MODE_HOMEKIT_TO_HASS.get(
|
||||||
characteristic['value'])
|
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:
|
elif ctype == CharacteristicsTypes.TEMPERATURE_CURRENT:
|
||||||
self._current_temp = characteristic['value']
|
self._current_temp = characteristic['value']
|
||||||
elif ctype == CharacteristicsTypes.TEMPERATURE_TARGET:
|
elif ctype == CharacteristicsTypes.TEMPERATURE_TARGET:
|
||||||
self._chars['target_temp'] = characteristic['iid']
|
|
||||||
self._features |= SUPPORT_TARGET_TEMPERATURE
|
|
||||||
self._target_temp = characteristic['value']
|
self._target_temp = characteristic['value']
|
||||||
|
|
||||||
def set_temperature(self, **kwargs):
|
def set_temperature(self, **kwargs):
|
||||||
|
@ -81,14 +95,14 @@ class HomeKitClimateDevice(HomeKitEntity, ClimateDevice):
|
||||||
temp = kwargs.get(ATTR_TEMPERATURE)
|
temp = kwargs.get(ATTR_TEMPERATURE)
|
||||||
|
|
||||||
characteristics = [{'aid': self._aid,
|
characteristics = [{'aid': self._aid,
|
||||||
'iid': self._chars['target_temp'],
|
'iid': self._chars['temperature.target'],
|
||||||
'value': temp}]
|
'value': temp}]
|
||||||
self.put_characteristics(characteristics)
|
self.put_characteristics(characteristics)
|
||||||
|
|
||||||
def set_operation_mode(self, operation_mode):
|
def set_operation_mode(self, operation_mode):
|
||||||
"""Set new target operation mode."""
|
"""Set new target operation mode."""
|
||||||
characteristics = [{'aid': self._aid,
|
characteristics = [{'aid': self._aid,
|
||||||
'iid': self._chars['target_mode'],
|
'iid': self._chars['heating-cooling.target'],
|
||||||
'value': MODE_HASS_TO_HOMEKIT[operation_mode]}]
|
'value': MODE_HASS_TO_HOMEKIT[operation_mode]}]
|
||||||
self.put_characteristics(characteristics)
|
self.put_characteristics(characteristics)
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,6 @@ class HomeKitGarageDoorCover(HomeKitEntity, CoverDevice):
|
||||||
def __init__(self, accessory, discovery_info):
|
def __init__(self, accessory, discovery_info):
|
||||||
"""Initialise the Cover."""
|
"""Initialise the Cover."""
|
||||||
super().__init__(accessory, discovery_info)
|
super().__init__(accessory, discovery_info)
|
||||||
self._name = None
|
|
||||||
self._state = None
|
self._state = None
|
||||||
self._obstruction_detected = None
|
self._obstruction_detected = None
|
||||||
self.lock_state = None
|
self.lock_state = None
|
||||||
|
@ -72,6 +71,20 @@ class HomeKitGarageDoorCover(HomeKitEntity, CoverDevice):
|
||||||
"""Define this cover as a garage door."""
|
"""Define this cover as a garage door."""
|
||||||
return 'garage'
|
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):
|
def update_characteristics(self, characteristics):
|
||||||
"""Synchronise the Cover state with Home Assistant."""
|
"""Synchronise the Cover state with Home Assistant."""
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
|
@ -81,18 +94,9 @@ class HomeKitGarageDoorCover(HomeKitEntity, CoverDevice):
|
||||||
ctype = characteristic['type']
|
ctype = characteristic['type']
|
||||||
ctype = CharacteristicsTypes.get_short(ctype)
|
ctype = CharacteristicsTypes.get_short(ctype)
|
||||||
if ctype == "door-state.current":
|
if ctype == "door-state.current":
|
||||||
self._chars['door-state.current'] = \
|
|
||||||
characteristic['iid']
|
|
||||||
self._state = CURRENT_GARAGE_STATE_MAP[characteristic['value']]
|
self._state = CURRENT_GARAGE_STATE_MAP[characteristic['value']]
|
||||||
elif ctype == "door-state.target":
|
|
||||||
self._chars['door-state.target'] = \
|
|
||||||
characteristic['iid']
|
|
||||||
elif ctype == "obstruction-detected":
|
elif ctype == "obstruction-detected":
|
||||||
self._chars['obstruction-detected'] = characteristic['iid']
|
|
||||||
self._obstruction_detected = characteristic['value']
|
self._obstruction_detected = characteristic['value']
|
||||||
elif ctype == "name":
|
|
||||||
self._chars['name'] = characteristic['iid']
|
|
||||||
self._name = characteristic['value']
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available(self):
|
def available(self):
|
||||||
|
@ -151,7 +155,6 @@ class HomeKitWindowCover(HomeKitEntity, CoverDevice):
|
||||||
def __init__(self, accessory, discovery_info):
|
def __init__(self, accessory, discovery_info):
|
||||||
"""Initialise the Cover."""
|
"""Initialise the Cover."""
|
||||||
super().__init__(accessory, discovery_info)
|
super().__init__(accessory, discovery_info)
|
||||||
self._name = None
|
|
||||||
self._state = None
|
self._state = None
|
||||||
self._position = None
|
self._position = None
|
||||||
self._tilt_position = None
|
self._tilt_position = None
|
||||||
|
@ -164,6 +167,26 @@ class HomeKitWindowCover(HomeKitEntity, CoverDevice):
|
||||||
"""Return True if entity is available."""
|
"""Return True if entity is available."""
|
||||||
return self._state is not None
|
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):
|
def update_characteristics(self, characteristics):
|
||||||
"""Synchronise the Cover state with Home Assistant."""
|
"""Synchronise the Cover state with Home Assistant."""
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
|
@ -173,43 +196,22 @@ class HomeKitWindowCover(HomeKitEntity, CoverDevice):
|
||||||
ctype = characteristic['type']
|
ctype = characteristic['type']
|
||||||
ctype = CharacteristicsTypes.get_short(ctype)
|
ctype = CharacteristicsTypes.get_short(ctype)
|
||||||
if ctype == "position.state":
|
if ctype == "position.state":
|
||||||
self._chars['position.state'] = \
|
|
||||||
characteristic['iid']
|
|
||||||
if 'value' in characteristic:
|
if 'value' in characteristic:
|
||||||
self._state = \
|
self._state = \
|
||||||
CURRENT_WINDOW_STATE_MAP[characteristic['value']]
|
CURRENT_WINDOW_STATE_MAP[characteristic['value']]
|
||||||
elif ctype == "position.current":
|
elif ctype == "position.current":
|
||||||
self._chars['position.current'] = \
|
|
||||||
characteristic['iid']
|
|
||||||
self._position = characteristic['value']
|
self._position = characteristic['value']
|
||||||
elif ctype == "position.target":
|
|
||||||
self._chars['position.target'] = \
|
|
||||||
characteristic['iid']
|
|
||||||
elif ctype == "position.hold":
|
elif ctype == "position.hold":
|
||||||
self._chars['position.hold'] = characteristic['iid']
|
|
||||||
if 'value' in characteristic:
|
if 'value' in characteristic:
|
||||||
self._hold = characteristic['value']
|
self._hold = characteristic['value']
|
||||||
elif ctype == "vertical-tilt.current":
|
elif ctype == "vertical-tilt.current":
|
||||||
self._chars['vertical-tilt.current'] = characteristic['iid']
|
|
||||||
if characteristic['value'] is not None:
|
if characteristic['value'] is not None:
|
||||||
self._tilt_position = characteristic['value']
|
self._tilt_position = characteristic['value']
|
||||||
elif ctype == "horizontal-tilt.current":
|
elif ctype == "horizontal-tilt.current":
|
||||||
self._chars['horizontal-tilt.current'] = characteristic['iid']
|
|
||||||
if characteristic['value'] is not None:
|
if characteristic['value'] is not None:
|
||||||
self._tilt_position = characteristic['value']
|
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":
|
elif ctype == "obstruction-detected":
|
||||||
self._chars['obstruction-detected'] = characteristic['iid']
|
|
||||||
self._obstruction_detected = characteristic['value']
|
self._obstruction_detected = characteristic['value']
|
||||||
elif ctype == "name":
|
|
||||||
self._chars['name'] = characteristic['iid']
|
|
||||||
if 'value' in characteristic:
|
|
||||||
self._name = characteristic['value']
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self):
|
||||||
|
|
|
@ -36,6 +36,30 @@ class HomeKitLight(HomeKitEntity, Light):
|
||||||
self._hue = None
|
self._hue = None
|
||||||
self._saturation = 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):
|
def update_characteristics(self, characteristics):
|
||||||
"""Synchronise light state with Home Assistant."""
|
"""Synchronise light state with Home Assistant."""
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
|
@ -45,23 +69,14 @@ class HomeKitLight(HomeKitEntity, Light):
|
||||||
ctype = characteristic['type']
|
ctype = characteristic['type']
|
||||||
ctype = CharacteristicsTypes.get_short(ctype)
|
ctype = CharacteristicsTypes.get_short(ctype)
|
||||||
if ctype == "on":
|
if ctype == "on":
|
||||||
self._chars['on'] = characteristic['iid']
|
|
||||||
self._on = characteristic['value']
|
self._on = characteristic['value']
|
||||||
elif ctype == 'brightness':
|
elif ctype == 'brightness':
|
||||||
self._chars['brightness'] = characteristic['iid']
|
|
||||||
self._features |= SUPPORT_BRIGHTNESS
|
|
||||||
self._brightness = characteristic['value']
|
self._brightness = characteristic['value']
|
||||||
elif ctype == 'color-temperature':
|
elif ctype == 'color-temperature':
|
||||||
self._chars['color-temperature'] = characteristic['iid']
|
|
||||||
self._features |= SUPPORT_COLOR_TEMP
|
|
||||||
self._color_temperature = characteristic['value']
|
self._color_temperature = characteristic['value']
|
||||||
elif ctype == "hue":
|
elif ctype == "hue":
|
||||||
self._chars['hue'] = characteristic['iid']
|
|
||||||
self._features |= SUPPORT_COLOR
|
|
||||||
self._hue = characteristic['value']
|
self._hue = characteristic['value']
|
||||||
elif ctype == "saturation":
|
elif ctype == "saturation":
|
||||||
self._chars['saturation'] = characteristic['iid']
|
|
||||||
self._features |= SUPPORT_COLOR
|
|
||||||
self._saturation = characteristic['value']
|
self._saturation = characteristic['value']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -51,6 +51,16 @@ class HomeKitLock(HomeKitEntity, LockDevice):
|
||||||
self._name = discovery_info['model']
|
self._name = discovery_info['model']
|
||||||
self._battery_level = 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.LOCK_MECHANISM_CURRENT_STATE,
|
||||||
|
CharacteristicsTypes.LOCK_MECHANISM_TARGET_STATE,
|
||||||
|
CharacteristicsTypes.BATTERY_LEVEL,
|
||||||
|
]
|
||||||
|
|
||||||
def update_characteristics(self, characteristics):
|
def update_characteristics(self, characteristics):
|
||||||
"""Synchronise the Lock state with Home Assistant."""
|
"""Synchronise the Lock state with Home Assistant."""
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
|
@ -60,14 +70,8 @@ class HomeKitLock(HomeKitEntity, LockDevice):
|
||||||
ctype = characteristic['type']
|
ctype = characteristic['type']
|
||||||
ctype = CharacteristicsTypes.get_short(ctype)
|
ctype = CharacteristicsTypes.get_short(ctype)
|
||||||
if ctype == "lock-mechanism.current-state":
|
if ctype == "lock-mechanism.current-state":
|
||||||
self._chars['lock-mechanism.current-state'] = \
|
|
||||||
characteristic['iid']
|
|
||||||
self._state = CURRENT_STATE_MAP[characteristic['value']]
|
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":
|
elif ctype == "battery-level":
|
||||||
self._chars['battery-level'] = characteristic['iid']
|
|
||||||
self._battery_level = characteristic['value']
|
self._battery_level = characteristic['value']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -33,6 +33,15 @@ class HomeKitSwitch(HomeKitEntity, SwitchDevice):
|
||||||
self._on = None
|
self._on = None
|
||||||
self._outlet_in_use = 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):
|
def update_characteristics(self, characteristics):
|
||||||
"""Synchronise the switch state with Home Assistant."""
|
"""Synchronise the switch state with Home Assistant."""
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
|
@ -42,10 +51,8 @@ class HomeKitSwitch(HomeKitEntity, SwitchDevice):
|
||||||
ctype = characteristic['type']
|
ctype = characteristic['type']
|
||||||
ctype = CharacteristicsTypes.get_short(ctype)
|
ctype = CharacteristicsTypes.get_short(ctype)
|
||||||
if ctype == "on":
|
if ctype == "on":
|
||||||
self._chars['on'] = characteristic['iid']
|
|
||||||
self._on = characteristic['value']
|
self._on = characteristic['value']
|
||||||
elif ctype == "outlet-in-use":
|
elif ctype == "outlet-in-use":
|
||||||
self._chars['outlet-in-use'] = characteristic['iid']
|
|
||||||
self._outlet_in_use = characteristic['value']
|
self._outlet_in_use = characteristic['value']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -8,7 +8,7 @@ from homekit.model.characteristics import (
|
||||||
from homekit.model import Accessory, get_id
|
from homekit.model import Accessory, get_id
|
||||||
|
|
||||||
from homeassistant.components.homekit_controller import (
|
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
|
from homeassistant.setup import async_setup_component
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
from tests.common import async_fire_time_changed, fire_service_discovered
|
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)
|
||||||
fire_service_discovered(hass, SERVICE_HOMEKIT, discovery_info)
|
await hass.async_block_till_done()
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
return Helper(hass, '.'.join((domain, 'testdevice')), pairing, accessory)
|
return Helper(hass, '.'.join((domain, 'testdevice')), pairing, accessory)
|
||||||
|
|
|
@ -39,7 +39,7 @@ def create_window_covering_service():
|
||||||
obstruction.value = False
|
obstruction.value = False
|
||||||
|
|
||||||
name = service.add_characteristic('name')
|
name = service.add_characteristic('name')
|
||||||
name.value = "Window Cover 1"
|
name.value = "testdevice"
|
||||||
|
|
||||||
return service
|
return service
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ def create_garage_door_opener_service():
|
||||||
obstruction.value = False
|
obstruction.value = False
|
||||||
|
|
||||||
name = service.add_characteristic('name')
|
name = service.add_characteristic('name')
|
||||||
name.value = "Garage Door Opener 1"
|
name.value = "testdevice"
|
||||||
|
|
||||||
return service
|
return service
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue