Ejemplo n.º 1
0
    async def async_step_user(self, user_input=None):
        """Handle a flow start."""
        import homekit

        errors = {}

        if user_input is not None:
            key = user_input['device']
            props = self.devices[key]['properties']
            self.hkid = props['id']
            self.model = props['md']
            return await self.async_step_pair()

        controller = homekit.Controller()
        all_hosts = await self.hass.async_add_executor_job(
            controller.discover, 5)

        self.devices = {}
        for host in all_hosts:
            status_flags = int(host['properties']['sf'])
            paired = not status_flags & 0x01
            if paired:
                continue
            self.devices[host['properties']['id']] = host

        if not self.devices:
            return self.async_abort(reason='no_devices')

        return self.async_show_form(step_id='user',
                                    errors=errors,
                                    data_schema=vol.Schema({
                                        vol.Required('device'):
                                        vol.In(self.devices.keys()),
                                    }))
Ejemplo n.º 2
0
 def __init__(self):
     """Initialize the homekit_controller flow."""
     self.model = None
     self.hkid = None
     self.devices = {}
     self.controller = homekit.Controller()
     self.finish_pairing = None
Ejemplo n.º 3
0
    async def async_step_pair(self, pair_info=None):
        """Pair with a new HomeKit accessory."""
        import homekit  # pylint: disable=import-error

        errors = {}

        if pair_info:
            code = pair_info['pairing_code']
            controller = homekit.Controller()
            try:
                await self.hass.async_add_executor_job(
                    controller.perform_pairing, self.hkid, self.hkid, code)

                pairing = controller.pairings.get(self.hkid)
                if pairing:
                    return await self._entry_from_accessory(pairing)

                errors['pairing_code'] = 'unable_to_pair'
            except homekit.AuthenticationError:
                errors['pairing_code'] = 'authentication_error'
            except homekit.UnknownError:
                errors['pairing_code'] = 'unknown_error'
            except homekit.UnavailableError:
                return self.async_abort(reason='already_paired')

        return self.async_show_form(step_id='pair',
                                    errors=errors,
                                    data_schema=vol.Schema({
                                        vol.Required('pairing_code'):
                                        vol.All(str, vol.Strip),
                                    }))
Ejemplo n.º 4
0
    def __init__(self):
        """Initialize the homekit_controller flow."""
        import homekit  # pylint: disable=import-error

        self.model = None
        self.hkid = None
        self.devices = {}
        self.controller = homekit.Controller()
        self.finish_pairing = None
Ejemplo n.º 5
0
async def async_setup(opp, config):
    """Set up for Homekit devices."""
    map_storage = opp.data[ENTITY_MAP] = EntityMapStorage(opp)
    await map_storage.async_initialize()

    opp.data[CONTROLLER] = homekit.Controller()
    opp.data[KNOWN_DEVICES] = {}

    return True
Ejemplo n.º 6
0
def setup(hass, config):
    """Set up for Homekit devices."""
    # pylint: disable=import-error
    import homekit
    from homekit.controller import Pairing

    hass.data[CONTROLLER] = controller = homekit.Controller()

    data_dir = os.path.join(hass.config.path(), HOMEKIT_DIR)
    if not os.path.isdir(data_dir):
        os.mkdir(data_dir)

    pairing_file = os.path.join(data_dir, PAIRING_FILE)
    if os.path.exists(pairing_file):
        controller.load_data(pairing_file)

    # Migrate any existing pairings to the new internal homekit_python format
    for device in os.listdir(data_dir):
        if not device.startswith('hk-'):
            continue
        alias = device[3:]
        if alias in controller.pairings:
            continue
        with open(os.path.join(data_dir, device)) as pairing_data_fp:
            pairing_data = json.load(pairing_data_fp)
        controller.pairings[alias] = Pairing(pairing_data)
        controller.save_data(pairing_file)

    def discovery_dispatch(service, discovery_info):
        """Dispatcher for Homekit discovery events."""
        # model, id
        host = discovery_info['host']
        port = discovery_info['port']
        model = discovery_info['properties']['md']
        hkid = discovery_info['properties']['id']
        config_num = int(discovery_info['properties']['c#'])

        if model in HOMEKIT_IGNORE:
            return

        # Only register a device once, but rescan if the config has changed
        if hkid in hass.data[KNOWN_DEVICES]:
            device = hass.data[KNOWN_DEVICES][hkid]
            if config_num > device.config_num and \
               device.pairing_info is not None:
                device.accessory_setup()
            return

        _LOGGER.debug('Discovered unique device %s', hkid)
        device = HKDevice(hass, host, port, model, hkid, config_num, config)
        hass.data[KNOWN_DEVICES][hkid] = device

    hass.data[KNOWN_ACCESSORIES] = {}
    hass.data[KNOWN_DEVICES] = {}
    discovery.listen(hass, SERVICE_HOMEKIT, discovery_dispatch)
    return True
Ejemplo n.º 7
0
async def async_setup(hass, config):
    """Set up for Homekit devices."""
    # pylint: disable=import-error
    import homekit

    map_storage = hass.data[ENTITY_MAP] = EntityMapStorage(hass)
    await map_storage.async_initialize()

    hass.data[CONTROLLER] = homekit.Controller()
    hass.data[KNOWN_DEVICES] = {}

    return True
Ejemplo n.º 8
0
async def async_setup(hass, config):
    """Set up for Homekit devices."""
    # pylint: disable=import-error
    import homekit
    from homekit.controller.ip_implementation import IpPairing

    map_storage = hass.data[ENTITY_MAP] = EntityMapStorage(hass)
    await map_storage.async_initialize()

    hass.data[CONTROLLER] = controller = homekit.Controller()

    old_pairings = await hass.async_add_executor_job(load_old_pairings, hass)
    for hkid, pairing_data in old_pairings.items():
        controller.pairings[hkid] = IpPairing(pairing_data)

    def discovery_dispatch(service, discovery_info):
        """Dispatcher for Homekit discovery events."""
        # model, id
        host = discovery_info['host']
        port = discovery_info['port']

        # Fold property keys to lower case, making them effectively
        # case-insensitive. Some HomeKit devices capitalize them.
        properties = {
            key.lower(): value
            for (key, value) in discovery_info['properties'].items()
        }

        model = properties['md']
        hkid = properties['id']
        config_num = int(properties['c#'])

        if model in HOMEKIT_IGNORE:
            return

        # Only register a device once, but rescan if the config has changed
        if hkid in hass.data[KNOWN_DEVICES]:
            device = hass.data[KNOWN_DEVICES][hkid]
            if config_num > device.config_num and \
               device.pairing is not None:
                device.refresh_entity_map(config_num)
            return

        _LOGGER.debug('Discovered unique device %s', hkid)
        device = HKDevice(hass, host, port, model, hkid, config_num, config)
        device.setup()

    hass.data[KNOWN_DEVICES] = {}

    await hass.async_add_executor_job(discovery.listen, hass, SERVICE_HOMEKIT,
                                      discovery_dispatch)

    return True
Ejemplo n.º 9
0
def setup(hass, config):
    """Set up for Homekit devices."""
    # pylint: disable=import-error
    import homekit
    from homekit.controller.ip_implementation import IpPairing

    hass.data[CONTROLLER] = controller = homekit.Controller()

    for hkid, pairing_data in load_old_pairings(hass).items():
        controller.pairings[hkid] = IpPairing(pairing_data)

    def discovery_dispatch(service, discovery_info):
        """Dispatcher for Homekit discovery events."""
        # model, id
        host = discovery_info['host']
        port = discovery_info['port']

        # Fold property keys to lower case, making them effectively
        # case-insensitive. Some HomeKit devices capitalize them.
        properties = {
            key.lower(): value
            for (key, value) in discovery_info['properties'].items()
        }

        model = properties['md']
        hkid = properties['id']
        config_num = int(properties['c#'])

        if model != BRID_HK_MODEL:
            return

        # Only register a device once, but rescan if the config has changed
        if hkid in hass.data[KNOWN_DEVICES]:
            device = hass.data[KNOWN_DEVICES][hkid]
            if config_num > device.config_num and \
               device.pairing is not None:
                device.accessory_setup()
            return

        _LOGGER.debug('Discovered Brid Air Purifier: %s', hkid)
        HKDevice(hass, host, port, model, hkid, config_num, config)

    hass.data[KNOWN_DEVICES] = {}
    hass.data[const.KNOWN_ENTITIES] = {}
    discovery.listen(hass, SERVICE_HOMEKIT, discovery_dispatch)
    return True
Ejemplo n.º 10
0
    async def async_step_pair(self, pair_info=None):
        """Pair with a new HomeKit accessory."""
        import homekit  # pylint: disable=import-error

        errors = {}

        if pair_info:
            code = pair_info['pairing_code']
            controller = homekit.Controller()
            try:
                await self.hass.async_add_executor_job(
                    controller.perform_pairing, self.hkid, self.hkid, code)

                pairing = controller.pairings.get(self.hkid)
                if pairing:
                    return await self._entry_from_accessory(pairing)

                errors['pairing_code'] = 'unable_to_pair'
            except homekit.AuthenticationError:
                errors['pairing_code'] = 'authentication_error'
            except homekit.UnknownError:
                errors['pairing_code'] = 'unknown_error'
            except homekit.MaxTriesError:
                errors['pairing_code'] = 'max_tries_error'
            except homekit.BusyError:
                errors['pairing_code'] = 'busy_error'
            except homekit.MaxPeersError:
                errors['pairing_code'] = 'max_peers_error'
            except homekit.AccessoryNotFoundError:
                return self.async_abort(reason='accessory_not_found_error')
            except homekit.UnavailableError:
                return self.async_abort(reason='already_paired')
            except Exception:  # pylint: disable=broad-except
                _LOGGER.exception(
                    "Pairing attempt failed with an unhandled exception")
                errors['pairing_code'] = 'pairing_failed'

        return self.async_show_form(step_id='pair',
                                    errors=errors,
                                    data_schema=vol.Schema({
                                        vol.Required('pairing_code'):
                                        vol.All(str, vol.Strip),
                                    }))