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()), }))
def __init__(self): """Initialize the homekit_controller flow.""" self.model = None self.hkid = None self.devices = {} self.controller = homekit.Controller() self.finish_pairing = None
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), }))
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
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
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
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
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
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
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), }))