Example #1
0
    def start_pairing(self, alias, accessory_id):
        """
        This starts a pairing attempt with the IP accessory identified by its id.
        It returns a callable (finish_pairing) which you must call with the pairing pin.

        Accessories can be found via the discover method. The id field is the accessory's id for the second parameter.

        The required pin is either printed on the accessory or displayed. Must be a string of the form 'XXX-YY-ZZZ'. If
        this format is not used, a MalformedPinError is raised.

        Important: no automatic saving of the pairing data is performed. If you don't do this, the information is lost
            and you have to reset the accessory!

        :param alias: the alias for the accessory in the controllers data
        :param accessory_id: the accessory's id
        :param pin: function to return the accessory's pin
        :raises AccessoryNotFoundError: if no accessory with the given id can be found
        :raises AlreadyPairedError: if the alias was already used
        :raises UnavailableError: if the device is already paired
        :raises MaxTriesError: if the device received more than 100 unsuccessful attempts
        :raises BusyError: if a parallel pairing is ongoing
        :raises AuthenticationError: if the verification of the device's SRP proof fails
        :raises MaxPeersError: if the device cannot accept an additional pairing
        :raises UnavailableError: on wrong pin
        """
        if not IP_TRANSPORT_SUPPORTED:
            raise TransportNotSupportedError('IP')
        if alias in self.pairings:
            raise AlreadyPairedError(
                'Alias "{a}" is already paired.'.format(a=alias))

        connection_data = find_device_ip_and_port(accessory_id)
        if connection_data is None:
            raise AccessoryNotFoundError(
                'Cannot find accessory with id "{i}".'.format(i=accessory_id))
        conn = HomeKitHTTPConnection(connection_data['ip'],
                                     port=connection_data['port'])

        try:
            write_fun = create_ip_pair_setup_write(conn)
            salt, pub_key = perform_pair_setup_part1(write_fun)
        except Exception:
            conn.close()
            raise

        def finish_pairing(pin):
            Controller.check_pin_format(pin)
            try:
                pairing = perform_pair_setup_part2(pin, str(uuid.uuid4()),
                                                   write_fun, salt, pub_key)
            finally:
                conn.close()
            pairing['AccessoryIP'] = connection_data['ip']
            pairing['AccessoryPort'] = connection_data['port']
            pairing['Connection'] = 'IP'
            self.pairings[alias] = IpPairing(pairing)

        return finish_pairing
Example #2
0
    def start_pairing_ble(self, alias, accessory_mac, adapter='hci0'):
        """
        This starts a pairing attempt with the Bluetooth LE accessory identified by its mac address.
        It returns a callable (finish_pairing) which you must call with the pairing pin.

        Accessories can be found via the discover method. The mac field is the accessory's mac for the second parameter.

        The required pin is either printed on the accessory or displayed. Must be a string of the form 'XXX-YY-ZZZ'.

        Important: no automatic saving of the pairing data is performed. If you don't do this, the information is lost
            and you have to reset the accessory!

        :param alias: the alias for the accessory in the controllers data
        :param accessory_mac: the accessory's mac address
        :param adapter: the bluetooth adapter to be used (defaults to hci0)
        # TODO add raised exceptions
        """
        if not BLE_TRANSPORT_SUPPORTED:
            raise TransportNotSupportedError('BLE')
        if alias in self.pairings:
            raise AlreadyPairedError(
                'Alias "{a}" is already paired.'.format(a=alias))

        from .ble_impl.device import DeviceManager
        manager = DeviceManager(adapter)
        device = manager.make_device(mac_address=accessory_mac)

        logging.debug('connecting to device')
        device.connect()
        logging.debug('connected to device')

        pair_setup_char, pair_setup_char_id = find_characteristic_by_uuid(
            device, ServicesTypes.PAIRING_SERVICE,
            CharacteristicsTypes.PAIR_SETUP)
        logging.debug('setup char: %s %s', pair_setup_char,
                      pair_setup_char.service.device)

        write_fun = create_ble_pair_setup_write(pair_setup_char,
                                                pair_setup_char_id)
        salt, pub_key = perform_pair_setup_part1(write_fun)

        def finish_pairing(pin):
            Controller.check_pin_format(pin)
            pairing = perform_pair_setup_part2(pin, str(uuid.uuid4()),
                                               write_fun, salt, pub_key)

            pairing['AccessoryMAC'] = accessory_mac
            pairing['Connection'] = 'BLE'

            self.pairings[alias] = BlePairing(pairing, adapter)

        return finish_pairing