def identify(self): """ This call can be used to trigger the identification of a paired accessory. A successful call should cause the accessory to perform some specific action by which it can be distinguished from the others (blink a LED for example). It uses the identify characteristic as described on page 152 of the spec. :return True, if the identification was run, False otherwise """ if not self.session: self.session = IpSession(self.pairing_data) if 'accessories' not in self.pairing_data: self.list_accessories_and_characteristics() # we are looking for a characteristic of the identify type identify_type = CharacteristicsTypes.get_uuid( CharacteristicsTypes.IDENTIFY) # search all accessories, all services and all characteristics for accessory in self.pairing_data['accessories']: aid = accessory['aid'] for service in accessory['services']: for characteristic in service['characteristics']: iid = characteristic['iid'] c_type = CharacteristicsTypes.get_uuid( characteristic['type']) if identify_type == c_type: # found the identify characteristic, so let's put a value there self.put_characteristics([(aid, iid, True)]) return True return False
def setup(self): """Configure an entity baed on its HomeKit characterstics metadata.""" # pylint: disable=import-error from homekit.model.characteristics import CharacteristicsTypes accessories = self._accessory.accessories get_uuid = CharacteristicsTypes.get_uuid characteristic_types = [ get_uuid(c) for c in self.get_characteristic_types() ] self.pollable_characteristics = [] self._chars = {} self._char_names = {} for accessory in accessories: if accessory["aid"] != self._aid: continue self._accessory_info = get_accessory_information(accessory) for service in accessory["services"]: if service["iid"] != self._iid: continue for char in service["characteristics"]: try: uuid = CharacteristicsTypes.get_uuid(char["type"]) except KeyError: # If a KeyError is raised its a non-standard # characteristic. We must ignore it in this case. continue if uuid not in characteristic_types: continue self._setup_characteristic(char)
def __init__(self, iid: int, characteristic_type: str, characteristic_format: str): if type(self) is AbstractCharacteristic: raise Exception( 'AbstractCharacteristic is an abstract class and cannot be instantiated directly' ) self.type = CharacteristicsTypes.get_uuid( characteristic_type) # page 65, see ServicesTypes self.iid = iid # page 65, unique instance id self.perms = [ CharacteristicPermissions.paired_read ] # page 65, array of values from CharacteristicPermissions self.format = characteristic_format # page 66, one of CharacteristicsTypes self.value = None # page 65, required but depends on format self.ev = None # boolean, not required, page 65 self.description = None # string, not required, page 65 self.unit = None # string, not required,page 66, valid values are in CharacteristicUnits self.minValue = None # number, not required, page 66, used if format is int* or float self.maxValue = None # number, not required, page 66, used if format is int* or float self.minStep = None # number, not required, page 66, used if format is int* or float self.maxLen = 64 # number, not required, page 66, used if format is string self.maxDataLen = 2097152 # number, not required, page 66, used if format is data self.valid_values = None # array, not required, see page 67, all numeric entries are allowed values self.valid_values_range = None # 2 element array, not required, see page 67 self._set_value_callback = None self._get_value_callback = None
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 self._accessory_info = get_accessory_information(accessory) for service in accessory['services']: if service['iid'] != self._iid: continue for char in service['characteristics']: try: uuid = CharacteristicsTypes.get_uuid(char['type']) except KeyError: # If a KeyError is raised its a non-standard # characteristic. We must ignore it in this case. continue if uuid not in characteristic_types: continue self._setup_characteristic(char)
def test_get_short(self): self.assertEqual(CharacteristicsTypes.get_short(CharacteristicsTypes.ON), 'on') self.assertEqual(CharacteristicsTypes.get_short(CharacteristicsTypes.get_uuid(CharacteristicsTypes.ON)), 'on') self.assertEqual(CharacteristicsTypes.get_short(CharacteristicsTypes.DOOR_STATE_TARGET), 'door-state.target') self.assertEqual(CharacteristicsTypes.get_short(CharacteristicsTypes.AIR_PURIFIER_STATE_CURRENT), 'air-purifier.state.current') self.assertEqual(CharacteristicsTypes.get_short('1a'), 'lock-management.auto-secure-timeout')
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']: try: uuid = CharacteristicsTypes.get_uuid(char['type']) except KeyError: # If a KeyError is raised its a non-standard # characteristic. We must ignore it in this case. continue if uuid not in characteristic_types: continue self._setup_characteristic(char)
def list_accessories_and_characteristics(self): """ This retrieves a current set of accessories and characteristics behind this pairing. :return: the accessory data as described in the spec on page 73 and following :raises AccessoryNotFoundError: if the device can not be found via zeroconf """ if not self.session: self.session = IpSession(self.pairing_data) try: response = self.session.get('/accessories') except (AccessoryDisconnectedError, EncryptionError): self.session.close() self.session = None raise tmp = response.read().decode() accessories = json.loads(tmp)['accessories'] for accessory in accessories: for service in accessory['services']: service['type'] = service['type'].upper() try: service['type'] = ServicesTypes.get_uuid(service['type']) except KeyError: pass for characteristic in service['characteristics']: characteristic['type'] = characteristic['type'].upper() try: characteristic['type'] = CharacteristicsTypes.get_uuid(characteristic['type']) except KeyError: pass self.pairing_data['accessories'] = accessories return accessories
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 test_get_short(self): self.assertEqual( CharacteristicsTypes.get_short(CharacteristicsTypes.ON), 'on') self.assertEqual( CharacteristicsTypes.get_short( CharacteristicsTypes.get_uuid(CharacteristicsTypes.ON)), 'on') self.assertEqual( CharacteristicsTypes.get_short( CharacteristicsTypes.DOOR_STATE_TARGET), 'door-state.target') self.assertEqual( CharacteristicsTypes.get_short( CharacteristicsTypes.AIR_PURIFIER_STATE_CURRENT), 'air-purifier.state.current') self.assertEqual(CharacteristicsTypes.get_short('1a'), 'Unknown Characteristic 1a')
def test_get_uuid_reverse(self): self.assertEqual(CharacteristicsTypes.get_uuid('public.hap.characteristic.on'), '00000025-0000-1000-8000-0026BB765291')
def test_get_uuid_forward(self): self.assertEqual(CharacteristicsTypes.get_uuid(CharacteristicsTypes.ON), '00000025-0000-1000-8000-0026BB765291')