def setup(hass, config): """Establish connection with Daikin.""" def discovery_dispatch(service, discovery_info): """Dispatcher for Daikin discovery events.""" host = discovery_info.get('ip') if daikin_api_setup(hass, host) is None: return for component in COMPONENT_TYPES: load_platform(hass, component, DOMAIN, discovery_info, config) discovery.listen(hass, SERVICE_DAIKIN, discovery_dispatch) for host in config.get(DOMAIN, {}).get(CONF_HOSTS, []): if daikin_api_setup(hass, host) is None: continue discovery_info = { 'ip': host, CONF_MONITORED_CONDITIONS: config[DOMAIN][CONF_MONITORED_CONDITIONS] } load_platform(hass, 'sensor', DOMAIN, discovery_info, config) return True
def setup(hass, config): """Common setup for WeMo devices.""" import pywemo global SUBSCRIPTION_REGISTRY SUBSCRIPTION_REGISTRY = pywemo.SubscriptionRegistry() SUBSCRIPTION_REGISTRY.start() def stop_wemo(event): """Shutdown Wemo subscriptions and subscription thread on exit.""" _LOGGER.info("Shutting down subscriptions.") SUBSCRIPTION_REGISTRY.stop() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_wemo) def discovery_dispatch(service, discovery_info): """Dispatcher for WeMo discovery events.""" # name, model, location, mac _, model_name, _, _, serial = discovery_info # Only register a device once if serial in KNOWN_DEVICES: return _LOGGER.debug('Discovered unique device %s', serial) KNOWN_DEVICES.append(serial) component = WEMO_MODEL_DISPATCH.get(model_name, 'switch') discovery.load_platform(hass, component, DOMAIN, discovery_info, config) discovery.listen(hass, SERVICE_WEMO, discovery_dispatch) hass.add_job(wemo_startup_scan, hass, config) return True
def test_listen(self, mock_setup_component): """Test discovery listen/discover combo.""" calls_single = [] calls_multi = [] def callback_single(service, info): """Service discovered callback.""" calls_single.append((service, info)) def callback_multi(service, info): """Service discovered callback.""" calls_multi.append((service, info)) discovery.listen(self.hass, 'test service', callback_single) discovery.listen(self.hass, ['test service', 'another service'], callback_multi) discovery.discover(self.hass, 'test service', 'discovery info', 'test_component') self.hass.pool.block_till_done() discovery.discover(self.hass, 'another service', 'discovery info', 'test_component') self.hass.pool.block_till_done() assert mock_setup_component.called assert mock_setup_component.call_args[0] == \ (self.hass, 'test_component', None) assert len(calls_single) == 1 assert calls_single[0] == ('test service', 'discovery info') assert len(calls_single) == 1 assert len(calls_multi) == 2 assert ['test service', 'another service'] == [info[0] for info in calls_multi]
def setup(hass, config): """Set up for Homekit devices.""" 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#']) # 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
def setup(hass, config): """Set up the Roku component.""" hass.data[DATA_ROKU] = {} def service_handler(service): """Handle service calls.""" if service.service == SERVICE_SCAN: scan_for_rokus(hass) def roku_discovered(service, info): """Set up an Roku that was auto discovered.""" _setup_roku(hass, config, { CONF_HOST: info['host'] }) discovery.listen(hass, SERVICE_ROKU, roku_discovered) for conf in config.get(DOMAIN, []): _setup_roku(hass, config, conf) hass.services.register( DOMAIN, SERVICE_SCAN, service_handler, schema=ROKU_SCAN_SCHEMA) return True
def setup(hass, config): """Set up for Homekit devices.""" 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
def setup(hass, config): """Set up the OctoPrint component.""" printers = hass.data[DOMAIN] = {} success = False def device_discovered(service, info): """Get called when an Octoprint server has been discovered.""" _LOGGER.debug("Found an Octoprint server: %s", info) discovery.listen(hass, SERVICE_OCTOPRINT, device_discovered) if DOMAIN not in config: # Skip the setup if there is no configuration present return True for printer in config[DOMAIN]: name = printer[CONF_NAME] protocol = "https" if printer[CONF_SSL] else "http" base_url = (f"{protocol}://{printer[CONF_HOST]}:{printer[CONF_PORT]}" f"{printer[CONF_PATH]}api/") api_key = printer[CONF_API_KEY] number_of_tools = printer[CONF_NUMBER_OF_TOOLS] bed = printer[CONF_BED] try: octoprint_api = OctoPrintAPI(base_url, api_key, bed, number_of_tools) printers[base_url] = octoprint_api octoprint_api.get("printer") octoprint_api.get("job") except requests.exceptions.RequestException as conn_err: _LOGGER.error("Error setting up OctoPrint API: %r", conn_err) continue sensors = printer[CONF_SENSORS][CONF_MONITORED_CONDITIONS] load_platform( hass, "sensor", DOMAIN, { "name": name, "base_url": base_url, "sensors": sensors }, config, ) b_sensors = printer[CONF_BINARY_SENSORS][CONF_MONITORED_CONDITIONS] load_platform( hass, "binary_sensor", DOMAIN, { "name": name, "base_url": base_url, "sensors": b_sensors }, config, ) success = True return success
def setup(hass, config): """Set up the Hue platform.""" config = config.get(DOMAIN) if config is None: config = {} if DOMAIN not in hass.data: hass.data[DOMAIN] = {} discovery.listen( hass, SERVICE_HUE, lambda service, discovery_info: bridge_discovered( hass, service, discovery_info)) bridges = config.get(CONF_BRIDGES, []) for bridge in bridges: filename = bridge.get(CONF_FILENAME) allow_unreachable = bridge.get(CONF_ALLOW_UNREACHABLE) allow_in_emulated_hue = bridge.get(CONF_ALLOW_IN_EMULATED_HUE) allow_hue_groups = bridge.get(CONF_ALLOW_HUE_GROUPS) host = bridge.get(CONF_HOST) if host is None: host = _find_host_from_config(hass, filename) if host is None: _LOGGER.error("No host found in configuration") return False setup_bridge(host, hass, filename, allow_unreachable, allow_in_emulated_hue, allow_hue_groups) return True
def setup(hass, config): """Set up the Yeelight bulbs.""" conf = config.get(DOMAIN, {}) yeelight_data = hass.data[DATA_YEELIGHT] = {} def device_discovered(service, info): _LOGGER.debug("Adding autodetected %s", info['hostname']) device_type = info['device_type'] name = "yeelight_%s_%s" % (device_type, info['properties']['mac']) ipaddr = info[CONF_HOST] device_config = DEVICE_SCHEMA({ CONF_NAME: name, CONF_MODEL: device_type }) _setup_device(hass, config, ipaddr, device_config) discovery.listen(hass, SERVICE_YEELIGHT, device_discovered) def update(event): for device in list(yeelight_data.values()): device.update() track_time_interval(hass, update, conf.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL)) if DOMAIN in config: for ipaddr, device_config in conf[CONF_DEVICES].items(): _LOGGER.debug("Adding configured %s", device_config[CONF_NAME]) _setup_device(hass, config, ipaddr, device_config) return True
def setup(hass, config): """Set up the Hue platform.""" config = config.get(DOMAIN) if config is None: config = {} if DOMAIN not in hass.data: hass.data[DOMAIN] = {} discovery.listen( hass, SERVICE_HUE, lambda service, discovery_info: bridge_discovered(hass, service, discovery_info)) bridges = config.get(CONF_BRIDGES, []) for bridge in bridges: filename = bridge.get(CONF_FILENAME) allow_unreachable = bridge.get(CONF_ALLOW_UNREACHABLE) allow_in_emulated_hue = bridge.get(CONF_ALLOW_IN_EMULATED_HUE) allow_hue_groups = bridge.get(CONF_ALLOW_HUE_GROUPS) host = bridge.get(CONF_HOST) if host is None: host = _find_host_from_config(hass, filename) if host is None: _LOGGER.error("No host found in configuration") return False setup_bridge(host, hass, filename, allow_unreachable, allow_in_emulated_hue, allow_hue_groups) return True
def setup(hass, config): cfg = config.get(DOMAIN) def device_discovered(service, info): # Called when betabrite device has been discovered. print("Discovered new BetaBrite device: {}".format(info)) discovery.listen(hass, SERVICE_BETABRITE, device_discovered) 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
def setup(hass, config): """Common setup for WeMo devices.""" import pywemo global SUBSCRIPTION_REGISTRY SUBSCRIPTION_REGISTRY = pywemo.SubscriptionRegistry() SUBSCRIPTION_REGISTRY.start() def stop_wemo(event): """Shutdown Wemo subscriptions and subscription thread on exit.""" _LOGGER.info("Shutting down subscriptions.") SUBSCRIPTION_REGISTRY.stop() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_wemo) def discovery_dispatch(service, discovery_info): """Dispatcher for WeMo discovery events.""" # name, model, location, mac _, model_name, _, _, serial = discovery_info # Only register a device once if serial in KNOWN_DEVICES: return _LOGGER.debug('Discovered unique device %s', serial) KNOWN_DEVICES.append(serial) component = WEMO_MODEL_DISPATCH.get(model_name, 'switch') discovery.load_platform(hass, component, DOMAIN, discovery_info, config) discovery.listen(hass, SERVICE_WEMO, discovery_dispatch) _LOGGER.info("Scanning for WeMo devices.") devices = [(device.host, device) for device in pywemo.discover_devices()] # Add static devices from the config file. devices.extend((address, None) for address in config.get(DOMAIN, {}).get(CONF_STATIC, [])) for address, device in devices: port = pywemo.ouimeaux_device.probe_wemo(address) if not port: _LOGGER.warning('Unable to probe wemo at %s', address) continue _LOGGER.info('Adding wemo at %s:%i', address, port) url = 'http://%s:%i/setup.xml' % (address, port) if device is None: device = pywemo.discovery.device_from_description(url, None) discovery_info = (device.name, device.model_name, url, device.mac, device.serialnumber) discovery.discover(hass, SERVICE_WEMO, discovery_info) return True
def setup(hass, config): """Set up the OctoPrint component.""" printers = hass.data[DOMAIN] = {} success = False def device_discovered(service, info): """Get called when an Octoprint server has been discovered.""" _LOGGER.debug("Found an Octoprint server: %s", info) discovery.listen(hass, SERVICE_OCTOPRINT, device_discovered) if DOMAIN not in config: # Skip the setup if there is no configuration present return True for printer in config[DOMAIN]: name = printer[CONF_NAME] ssl = 's' if printer[CONF_SSL] else '' base_url = 'http{}://{}:{}{}api/'.format(ssl, printer[CONF_HOST], printer[CONF_PORT], printer[CONF_PATH]) api_key = printer[CONF_API_KEY] number_of_tools = printer[CONF_NUMBER_OF_TOOLS] bed = printer[CONF_BED] try: octoprint_api = OctoPrintAPI(base_url, api_key, bed, number_of_tools) printers[base_url] = octoprint_api octoprint_api.get('printer') octoprint_api.get('job') except requests.exceptions.RequestException as conn_err: _LOGGER.error("Error setting up OctoPrint API: %r", conn_err) continue sensors = printer[CONF_SENSORS][CONF_MONITORED_CONDITIONS] load_platform(hass, 'sensor', DOMAIN, { 'name': name, 'base_url': base_url, 'sensors': sensors }, config) b_sensors = printer[CONF_BINARY_SENSORS][CONF_MONITORED_CONDITIONS] load_platform(hass, 'binary_sensor', DOMAIN, { 'name': name, 'base_url': base_url, 'sensors': b_sensors }, config) success = True return success
def setup(hass, config): """Set up the Hue platform.""" conf = config.get(DOMAIN) if conf is None: conf = {} if DOMAIN not in hass.data: hass.data[DOMAIN] = {} discovery.listen( hass, SERVICE_HUE, lambda service, discovery_info: bridge_discovered(hass, service, discovery_info)) # User has configured bridges if CONF_BRIDGES in conf: bridges = conf[CONF_BRIDGES] # Component is part of config but no bridges specified, discover. elif DOMAIN in config: # discover from nupnp hosts = requests.get(API_NUPNP).json() bridges = [{ CONF_HOST: entry['internalipaddress'], CONF_FILENAME: '.hue_{}.conf'.format(entry['id']), } for entry in hosts] else: # Component not specified in config, we're loaded via discovery bridges = [] for bridge in bridges: filename = bridge.get(CONF_FILENAME) allow_unreachable = bridge.get(CONF_ALLOW_UNREACHABLE) allow_in_emulated_hue = bridge.get(CONF_ALLOW_IN_EMULATED_HUE) allow_hue_groups = bridge.get(CONF_ALLOW_HUE_GROUPS) host = bridge.get(CONF_HOST) if host is None: host = _find_host_from_config(hass, filename) if host is None: _LOGGER.error("No host found in configuration") return False setup_bridge(host, hass, filename, allow_unreachable, allow_in_emulated_hue, allow_hue_groups) return True
def setup(hass, config): """Set up the Hue platform.""" conf = config.get(DOMAIN) if conf is None: conf = {} if DOMAIN not in hass.data: hass.data[DOMAIN] = {} discovery.listen( hass, SERVICE_HUE, lambda service, discovery_info: bridge_discovered( hass, service, discovery_info)) # User has configured bridges if CONF_BRIDGES in conf: bridges = conf[CONF_BRIDGES] # Component is part of config but no bridges specified, discover. elif DOMAIN in config: # discover from nupnp hosts = requests.get(API_NUPNP).json() bridges = [{ CONF_HOST: entry['internalipaddress'], CONF_FILENAME: '.hue_{}.conf'.format(entry['id']), } for entry in hosts] else: # Component not specified in config, we're loaded via discovery bridges = [] for bridge in bridges: filename = bridge.get(CONF_FILENAME) allow_unreachable = bridge.get(CONF_ALLOW_UNREACHABLE) allow_in_emulated_hue = bridge.get(CONF_ALLOW_IN_EMULATED_HUE) allow_hue_groups = bridge.get(CONF_ALLOW_HUE_GROUPS) host = bridge.get(CONF_HOST) if host is None: host = _find_host_from_config(hass, filename) if host is None: _LOGGER.error("No host found in configuration") return False setup_bridge(host, hass, filename, allow_unreachable, allow_in_emulated_hue, allow_hue_groups) return True
def setup(hass, config): """Set up the Yeelight bulbs.""" conf = config.get(DOMAIN, {}) yeelight_data = hass.data[DATA_YEELIGHT] = {} def device_discovered(_, info): _LOGGER.debug("Adding autodetected %s", info['hostname']) device_type = info['device_type'] name = "yeelight_%s_%s" % (device_type, info['properties']['mac']) ipaddr = info[CONF_HOST] device_config = DEVICE_SCHEMA({ CONF_NAME: name, CONF_MODEL: device_type }) _setup_device(hass, config, ipaddr, device_config) discovery.listen(hass, SERVICE_YEELIGHT, device_discovered) def update(_): for device in list(yeelight_data.values()): device.update() track_time_interval( hass, update, conf.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL) ) def load_platforms(ipaddr): platform_config = hass.data[DATA_YEELIGHT][ipaddr].config.copy() platform_config[CONF_HOST] = ipaddr platform_config[CONF_CUSTOM_EFFECTS] = \ config.get(DOMAIN, {}).get(CONF_CUSTOM_EFFECTS, {}) load_platform(hass, LIGHT_DOMAIN, DOMAIN, platform_config, config) load_platform(hass, BINARY_SENSOR_DOMAIN, DOMAIN, platform_config, config) dispatcher_connect(hass, DEVICE_INITIALIZED, load_platforms) if DOMAIN in config: for ipaddr, device_config in conf[CONF_DEVICES].items(): _LOGGER.debug("Adding configured %s", device_config[CONF_NAME]) _setup_device(hass, config, ipaddr, device_config) return True
def setup(hass, config): """Set up the OctoPrint component.""" printers = hass.data[DOMAIN] = {} success = False def device_discovered(service, info): """Get called when an Octoprint server has been discovered.""" _LOGGER.debug("Found an Octoprint server: %s", info) discovery.listen(hass, SERVICE_OCTOPRINT, device_discovered) if DOMAIN not in config: # Skip the setup if there is no configuration present return True for printer in config[DOMAIN]: name = printer[CONF_NAME] ssl = 's' if printer[CONF_SSL] else '' base_url = 'http{}://{}:{}{}api/'.format(ssl, printer[CONF_HOST], printer[CONF_PORT], printer[CONF_PATH]) api_key = printer[CONF_API_KEY] number_of_tools = printer[CONF_NUMBER_OF_TOOLS] bed = printer[CONF_BED] try: octoprint_api = OctoPrintAPI(base_url, api_key, bed, number_of_tools) printers[base_url] = octoprint_api octoprint_api.get('printer') octoprint_api.get('job') except requests.exceptions.RequestException as conn_err: _LOGGER.error("Error setting up OctoPrint API: %r", conn_err) continue sensors = printer[CONF_SENSORS][CONF_MONITORED_CONDITIONS] load_platform(hass, 'sensor', DOMAIN, {'name': name, 'base_url': base_url, 'sensors': sensors}, config) b_sensors = printer[CONF_BINARY_SENSORS][CONF_MONITORED_CONDITIONS] load_platform(hass, 'binary_sensor', DOMAIN, {'name': name, 'base_url': base_url, 'sensors': b_sensors}, config) success = True return success
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
def setup(hass, base_config): """Common setup for Axis devices.""" def _shutdown(call): # pylint: disable=unused-argument """Stop the metadatastream on shutdown.""" for serialnumber, device in AXIS_DEVICES.items(): _LOGGER.info("Stopping metadatastream for %s.", serialnumber) device.stop_metadatastream() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown) def axis_device_discovered(service, discovery_info): """Called when axis devices has been found.""" host = discovery_info['host'] name = discovery_info['hostname'] serialnumber = discovery_info['properties']['macaddress'] if serialnumber not in AXIS_DEVICES: config_file = _read_config(hass) if serialnumber in config_file: try: config = DEVICE_SCHEMA(config_file[serialnumber]) except vol.Invalid as err: _LOGGER.error("Bad data from %s. %s", CONFIG_FILE, err) return False if not setup_device(hass, config): _LOGGER.error("Couldn\'t set up %s", config['name']) else: request_configuration(hass, name, host, serialnumber) discovery.listen(hass, SERVICE_AXIS, axis_device_discovered) if DOMAIN in base_config: for device in base_config[DOMAIN]: config = base_config[DOMAIN][device] if CONF_NAME not in config: config[CONF_NAME] = device if not setup_device(hass, config): _LOGGER.error("Couldn\'t set up %s", config['name']) return True
def setup(hass, config): """Set up the Roku component.""" hass.data[DATA_ROKU] = {} def service_handler(service): """Handle service calls.""" if service.service == SERVICE_SCAN: scan_for_rokus(hass) def roku_discovered(service, info): """Set up an Roku that was auto discovered.""" _setup_roku(hass, config, {CONF_HOST: info["host"]}) discovery.listen(hass, SERVICE_ROKU, roku_discovered) for conf in config.get(DOMAIN, []): _setup_roku(hass, config, conf) hass.services.register(DOMAIN, SERVICE_SCAN, service_handler, schema=ROKU_SCAN_SCHEMA) return True
def setup(hass, config): """Set up the Yeelight bulbs.""" conf = config.get(DOMAIN, {}) yeelight_data = hass.data[DATA_YEELIGHT] = {} def device_discovered(service, info): _LOGGER.debug("Adding autodetected %s", info['hostname']) device_type = info['device_type'] name = "yeelight_%s_%s" % (device_type, info['properties']['mac']) ipaddr = info[CONF_HOST] device_config = DEVICE_SCHEMA({ CONF_NAME: name, CONF_MODEL: device_type }) _setup_device(hass, config, ipaddr, device_config) discovery.listen(hass, SERVICE_YEELIGHT, device_discovered) def update(event): for device in yeelight_data.values(): device.update() track_time_interval( hass, update, conf.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL) ) if DOMAIN in config: for ipaddr, device_config in conf[CONF_DEVICES].items(): _LOGGER.debug("Adding configured %s", device_config[CONF_NAME]) _setup_device(hass, config, ipaddr, device_config) return True
def setup(hass, config): """Set up the Xiaomi component.""" gateways = [] interface = 'any' discovery_retry = 3 if DOMAIN in config: gateways = config[DOMAIN][CONF_GATEWAYS] interface = config[DOMAIN][CONF_INTERFACE] discovery_retry = config[DOMAIN][CONF_DISCOVERY_RETRY] async def xiaomi_gw_discovered(service, discovery_info): """Perform action when Xiaomi Gateway device(s) has been found.""" # We don't need to do anything here, the purpose of Home Assistant's # discovery service is to just trigger loading of this # component, and then its own discovery process kicks in. discovery.listen(hass, SERVICE_XIAOMI_GW, xiaomi_gw_discovered) from xiaomi_gateway import XiaomiGatewayDiscovery xiaomi = hass.data[PY_XIAOMI_GATEWAY] = XiaomiGatewayDiscovery( hass.add_job, gateways, interface) _LOGGER.debug("Expecting %s gateways", len(gateways)) for k in range(discovery_retry): _LOGGER.info("Discovering Xiaomi Gateways (Try %s)", k + 1) xiaomi.discover_gateways() if len(xiaomi.gateways) >= len(gateways): break if not xiaomi.gateways: _LOGGER.error("No gateway discovered") return False xiaomi.listen() _LOGGER.debug("Gateways discovered. Listening for broadcasts") for component in ['binary_sensor', 'sensor', 'switch', 'light', 'cover', 'lock']: discovery.load_platform(hass, component, DOMAIN, {}, config) def stop_xiaomi(event): """Stop Xiaomi Socket.""" _LOGGER.info("Shutting down Xiaomi Hub") xiaomi.stop_listen() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_xiaomi) def play_ringtone_service(call): """Service to play ringtone through Gateway.""" ring_id = call.data.get(ATTR_RINGTONE_ID) gateway = call.data.get(ATTR_GW_MAC) kwargs = {'mid': ring_id} ring_vol = call.data.get(ATTR_RINGTONE_VOL) if ring_vol is not None: kwargs['vol'] = ring_vol gateway.write_to_hub(gateway.sid, **kwargs) def stop_ringtone_service(call): """Service to stop playing ringtone on Gateway.""" gateway = call.data.get(ATTR_GW_MAC) gateway.write_to_hub(gateway.sid, mid=10000) def add_device_service(call): """Service to add a new sub-device within the next 30 seconds.""" gateway = call.data.get(ATTR_GW_MAC) gateway.write_to_hub(gateway.sid, join_permission='yes') hass.components.persistent_notification.async_create( 'Join permission enabled for 30 seconds! ' 'Please press the pairing button of the new device once.', title='Xiaomi Aqara Gateway') def remove_device_service(call): """Service to remove a sub-device from the gateway.""" device_id = call.data.get(ATTR_DEVICE_ID) gateway = call.data.get(ATTR_GW_MAC) gateway.write_to_hub(gateway.sid, remove_device=device_id) gateway_only_schema = _add_gateway_to_schema(xiaomi, vol.Schema({})) hass.services.register( DOMAIN, SERVICE_PLAY_RINGTONE, play_ringtone_service, schema=_add_gateway_to_schema(xiaomi, SERVICE_SCHEMA_PLAY_RINGTONE)) hass.services.register( DOMAIN, SERVICE_STOP_RINGTONE, stop_ringtone_service, schema=gateway_only_schema) hass.services.register( DOMAIN, SERVICE_ADD_DEVICE, add_device_service, schema=gateway_only_schema) hass.services.register( DOMAIN, SERVICE_REMOVE_DEVICE, remove_device_service, schema=_add_gateway_to_schema(xiaomi, SERVICE_SCHEMA_REMOVE_DEVICE)) return True
def setup(hass, config): """Set up for WeMo devices.""" import pywemo global SUBSCRIPTION_REGISTRY SUBSCRIPTION_REGISTRY = pywemo.SubscriptionRegistry() SUBSCRIPTION_REGISTRY.start() def stop_wemo(event): """Shutdown Wemo subscriptions and subscription thread on exit.""" _LOGGER.info("Shutting down subscriptions.") SUBSCRIPTION_REGISTRY.stop() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_wemo) def discovery_dispatch(service, discovery_info): """Dispatcher for WeMo discovery events.""" # name, model, location, mac model_name = discovery_info.get('model_name') serial = discovery_info.get('serial') # Only register a device once if serial in KNOWN_DEVICES: return _LOGGER.debug('Discovered unique device %s', serial) KNOWN_DEVICES.append(serial) component = WEMO_MODEL_DISPATCH.get(model_name, 'switch') discovery.load_platform(hass, component, DOMAIN, discovery_info, config) discovery.listen(hass, SERVICE_WEMO, discovery_dispatch) def setup_url_for_device(device): """Determine setup.xml url for given device.""" return 'http://{}:{}/setup.xml'.format(device.host, device.port) def setup_url_for_address(host, port): """Determine setup.xml url for given host and port pair.""" if not port: port = pywemo.ouimeaux_device.probe_wemo(host) if not port: return None return 'http://{}:{}/setup.xml'.format(host, port) devices = [] for host, port in config.get(DOMAIN, {}).get(CONF_STATIC, []): url = setup_url_for_address(host, port) if not url: _LOGGER.error('Unable to get description url for %s', '{}:{}'.format(host, port) if port else host) return False try: device = pywemo.discovery.device_from_description(url, None) except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as err: _LOGGER.error('Unable to access %s (%s)', url, err) return False devices.append((url, device)) _LOGGER.info("Scanning for WeMo devices.") devices.extend((setup_url_for_device(device), device) for device in pywemo.discover_devices()) for url, device in devices: _LOGGER.info('Adding wemo at %s:%i', device.host, device.port) discovery_info = { 'model_name': device.model_name, 'serial': device.serialnumber, 'mac_address': device.mac, 'ssdp_description': url, } discovery.discover(hass, SERVICE_WEMO, discovery_info) return True
def setup(hass, config): """Common setup for Axis devices.""" def _shutdown(call): # pylint: disable=unused-argument """Stop the event stream on shutdown.""" for serialnumber, device in AXIS_DEVICES.items(): _LOGGER.info("Stopping event stream for %s.", serialnumber) device.stop() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown) def axis_device_discovered(service, discovery_info): """Called when axis devices has been found.""" host = discovery_info[CONF_HOST] name = discovery_info['hostname'] serialnumber = discovery_info['properties']['macaddress'] if serialnumber not in AXIS_DEVICES: config_file = load_json(hass.config.path(CONFIG_FILE)) if serialnumber in config_file: # Device config previously saved to file try: device_config = DEVICE_SCHEMA(config_file[serialnumber]) device_config[CONF_HOST] = host except vol.Invalid as err: _LOGGER.error("Bad data from %s. %s", CONFIG_FILE, err) return False if not setup_device(hass, config, device_config): _LOGGER.error("Couldn\'t set up %s", device_config[CONF_NAME]) else: # New device, create configuration request for UI request_configuration(hass, config, name, host, serialnumber) else: # Device already registered, but on a different IP device = AXIS_DEVICES[serialnumber] device.config.host = host dispatcher_send(hass, DOMAIN + '_' + device.name + '_new_ip', host) # Register discovery service discovery.listen(hass, SERVICE_AXIS, axis_device_discovered) if DOMAIN in config: for device in config[DOMAIN]: device_config = config[DOMAIN][device] if CONF_NAME not in device_config: device_config[CONF_NAME] = device if not setup_device(hass, config, device_config): _LOGGER.error("Couldn\'t set up %s", device_config[CONF_NAME]) def vapix_service(call): """Service to send a message.""" for _, device in AXIS_DEVICES.items(): if device.name == call.data[CONF_NAME]: response = device.vapix.do_request(call.data[SERVICE_CGI], call.data[SERVICE_ACTION], call.data[SERVICE_PARAM]) hass.bus.fire(SERVICE_VAPIX_CALL_RESPONSE, response) return True _LOGGER.info("Couldn\'t find device %s", call.data[CONF_NAME]) return False # Register service with Home Assistant. hass.services.register(DOMAIN, SERVICE_VAPIX_CALL, vapix_service, schema=SERVICE_SCHEMA) return True
def setup(hass, config): """Common setup for Axis devices.""" def _shutdown(call): # pylint: disable=unused-argument """Stop the metadatastream on shutdown.""" for serialnumber, device in AXIS_DEVICES.items(): _LOGGER.info("Stopping metadatastream for %s.", serialnumber) device.stop_metadatastream() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown) def axis_device_discovered(service, discovery_info): """Called when axis devices has been found.""" host = discovery_info[CONF_HOST] name = discovery_info['hostname'] serialnumber = discovery_info['properties']['macaddress'] if serialnumber not in AXIS_DEVICES: config_file = _read_config(hass) if serialnumber in config_file: # Device config saved to file try: device_config = DEVICE_SCHEMA(config_file[serialnumber]) device_config[CONF_HOST] = host except vol.Invalid as err: _LOGGER.error("Bad data from %s. %s", CONFIG_FILE, err) return False if not setup_device(hass, config, device_config): _LOGGER.error("Couldn\'t set up %s", device_config[CONF_NAME]) else: # New device, create configuration request for UI request_configuration(hass, config, name, host, serialnumber) else: # Device already registered, but on a different IP device = AXIS_DEVICES[serialnumber] device.url = host async_dispatcher_send(hass, DOMAIN + '_' + device.name + '_new_ip', host) # Register discovery service discovery.listen(hass, SERVICE_AXIS, axis_device_discovered) if DOMAIN in config: for device in config[DOMAIN]: device_config = config[DOMAIN][device] if CONF_NAME not in device_config: device_config[CONF_NAME] = device if not setup_device(hass, config, device_config): _LOGGER.error("Couldn\'t set up %s", device_config[CONF_NAME]) # Services to communicate with device. descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) def vapix_service(call): """Service to send a message.""" for _, device in AXIS_DEVICES.items(): if device.name == call.data[CONF_NAME]: response = device.do_request(call.data[SERVICE_CGI], call.data[SERVICE_ACTION], call.data[SERVICE_PARAM]) hass.bus.async_fire(SERVICE_VAPIX_CALL_RESPONSE, response) return True _LOGGER.info("Couldn\'t find device %s", call.data[CONF_NAME]) return False # Register service with Home Assistant. hass.services.register(DOMAIN, SERVICE_VAPIX_CALL, vapix_service, descriptions[DOMAIN][SERVICE_VAPIX_CALL], schema=SERVICE_SCHEMA) return True
def setup(hass, config): """Set up for WeMo devices.""" import pywemo # Keep track of WeMo devices devices = [] # Keep track of WeMo device subscriptions for push updates global SUBSCRIPTION_REGISTRY SUBSCRIPTION_REGISTRY = pywemo.SubscriptionRegistry() SUBSCRIPTION_REGISTRY.start() def stop_wemo(event): """Shutdown Wemo subscriptions and subscription thread on exit.""" _LOGGER.debug("Shutting down WeMo event subscriptions") SUBSCRIPTION_REGISTRY.stop() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_wemo) def setup_url_for_device(device): """Determine setup.xml url for given device.""" return 'http://{}:{}/setup.xml'.format(device.host, device.port) def setup_url_for_address(host, port): """Determine setup.xml url for given host and port pair.""" if not port: port = pywemo.ouimeaux_device.probe_wemo(host) if not port: return None return 'http://{}:{}/setup.xml'.format(host, port) def discovery_dispatch(service, discovery_info): """Dispatcher for incoming WeMo discovery events.""" # name, model, location, mac model_name = discovery_info.get('model_name') serial = discovery_info.get('serial') # Only register a device once if serial in KNOWN_DEVICES: _LOGGER.debug("Ignoring known device %s %s", service, discovery_info) return _LOGGER.debug("Discovered unique WeMo device: %s", serial) KNOWN_DEVICES.append(serial) component = WEMO_MODEL_DISPATCH.get(model_name, 'switch') discovery.load_platform(hass, component, DOMAIN, discovery_info, config) discovery.listen(hass, SERVICE_WEMO, discovery_dispatch) def discover_wemo_devices(now): """Run discovery for WeMo devices.""" _LOGGER.debug("Beginning WeMo device discovery...") _LOGGER.debug("Adding statically configured WeMo devices...") for host, port in config.get(DOMAIN, {}).get(CONF_STATIC, []): url = setup_url_for_address(host, port) if not url: _LOGGER.error('Unable to get description url for WeMo at: %s', '{}:{}'.format(host, port) if port else host) continue try: device = pywemo.discovery.device_from_description(url, None) except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as err: _LOGGER.error("Unable to access WeMo at %s (%s)", url, err) continue if not [ d[1] for d in devices if d[1].serialnumber == device.serialnumber ]: devices.append((url, device)) if config.get(DOMAIN, {}).get(CONF_DISCOVERY): _LOGGER.debug("Scanning network for WeMo devices...") for device in pywemo.discover_devices(): if not [ d[1] for d in devices if d[1].serialnumber == device.serialnumber ]: devices.append((setup_url_for_device(device), device)) for url, device in devices: _LOGGER.debug("Adding WeMo device at %s:%i", device.host, device.port) discovery_info = { 'model_name': device.model_name, 'serial': device.serialnumber, 'mac_address': device.mac, 'ssdp_description': url, } discovery.discover(hass, SERVICE_WEMO, discovery_info) _LOGGER.debug("WeMo device discovery has finished") hass.bus.listen_once(EVENT_HOMEASSISTANT_START, discover_wemo_devices) return True
def setup_plex(config=None, discovery_info=None, configurator_info=None): """Return assembled server_config dict.""" json_file = hass.config.path(PLEX_CONFIG_FILE) file_config = load_json(json_file) host_and_port = None if config: server_config = config if CONF_HOST in server_config: host_and_port = ( f"{server_config.pop(CONF_HOST)}:{server_config.pop(CONF_PORT)}" ) if MP_DOMAIN in server_config: hass.data[PLEX_MEDIA_PLAYER_OPTIONS] = server_config.pop( MP_DOMAIN) elif file_config: _LOGGER.debug("Loading config from %s", json_file) host_and_port, server_config = file_config.popitem() server_config[CONF_VERIFY_SSL] = server_config.pop("verify") elif discovery_info: server_config = {} host_and_port = f"{discovery_info[CONF_HOST]}:{discovery_info[CONF_PORT]}" elif configurator_info: server_config = configurator_info host_and_port = server_config["host_and_port"] else: discovery.listen(hass, SERVICE_PLEX, server_discovered) return True if host_and_port: use_ssl = server_config.get(CONF_SSL, DEFAULT_SSL) http_prefix = "https" if use_ssl else "http" server_config[CONF_URL] = f"{http_prefix}://{host_and_port}" plex_server = PlexServer(server_config) try: plex_server.connect() except requests.exceptions.ConnectionError as error: _LOGGER.error( "Plex server could not be reached, please verify host and port: [%s]", error, ) return False except ( plexapi.exceptions.BadRequest, plexapi.exceptions.Unauthorized, plexapi.exceptions.NotFound, ) as error: _LOGGER.error( "Connection to Plex server failed, please verify token and SSL settings: [%s]", error, ) request_configuration(host_and_port) return False else: hass.data[PLEX_DOMAIN][SERVERS][ plex_server.machine_identifier] = plex_server if host_and_port in hass.data[PLEX_DOMAIN][CONFIGURING]: request_id = hass.data[PLEX_DOMAIN][CONFIGURING].pop( host_and_port) configurator = hass.components.configurator configurator.request_done(request_id) _LOGGER.debug("Discovery configuration done") if configurator_info: # Write plex.conf if created via discovery/configurator save_json( hass.config.path(PLEX_CONFIG_FILE), { host_and_port: { CONF_TOKEN: server_config[CONF_TOKEN], CONF_SSL: use_ssl, "verify": server_config[CONF_VERIFY_SSL], } }, ) if not hass.data.get(PLEX_MEDIA_PLAYER_OPTIONS): hass.data[PLEX_MEDIA_PLAYER_OPTIONS] = MEDIA_PLAYER_SCHEMA({}) for platform in PLATFORMS: hass.helpers.discovery.load_platform(platform, PLEX_DOMAIN, {}, original_config) return True
def setup(hass: HomeAssistantType, config: ConfigType): """Setup device tracker.""" yaml_path = hass.config.path(YAML_DEVICES) try: conf = _CONFIG_SCHEMA(config).get(DOMAIN, []) except vol.Invalid as ex: log_exception(ex, DOMAIN, config) return False else: conf = conf[0] if len(conf) > 0 else {} consider_home = conf.get(CONF_CONSIDER_HOME, timedelta(seconds=DEFAULT_CONSIDER_HOME)) track_new = conf.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW) devices = load_config(yaml_path, hass, consider_home) tracker = DeviceTracker(hass, consider_home, track_new, devices) def setup_platform(p_type, p_config, disc_info=None): """Setup a device tracker platform.""" platform = prepare_setup_platform(hass, config, DOMAIN, p_type) if platform is None: return try: if hasattr(platform, 'get_scanner'): scanner = platform.get_scanner(hass, {DOMAIN: p_config}) if scanner is None: _LOGGER.error('Error setting up platform %s', p_type) return setup_scanner_platform(hass, p_config, scanner, tracker.see) return if not platform.setup_scanner(hass, p_config, tracker.see): _LOGGER.error('Error setting up platform %s', p_type) except Exception: # pylint: disable=broad-except _LOGGER.exception('Error setting up platform %s', p_type) for p_type, p_config in config_per_platform(config, DOMAIN): setup_platform(p_type, p_config) def device_tracker_discovered(service, info): """Called when a device tracker platform is discovered.""" setup_platform(DISCOVERY_PLATFORMS[service], {}, info) discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), device_tracker_discovered) def update_stale(now): """Clean up stale devices.""" tracker.update_stale(now) track_utc_time_change(hass, update_stale, second=range(0, 60, 5)) tracker.setup_group() def see_service(call): """Service to see a device.""" args = { key: value for key, value in call.data.items() if key in (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME, ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY, ATTR_ATTRIBUTES) } tracker.see(**args) descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) hass.services.register(DOMAIN, SERVICE_SEE, see_service, descriptions.get(SERVICE_SEE)) return True
def setup(hass, config): """Set up for WeMo devices.""" import pywemo # Keep track of WeMo devices devices = [] # Keep track of WeMo device subscriptions for push updates global SUBSCRIPTION_REGISTRY SUBSCRIPTION_REGISTRY = pywemo.SubscriptionRegistry() SUBSCRIPTION_REGISTRY.start() def stop_wemo(event): """Shutdown Wemo subscriptions and subscription thread on exit.""" _LOGGER.debug("Shutting down WeMo event subscriptions") SUBSCRIPTION_REGISTRY.stop() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_wemo) def setup_url_for_device(device): """Determine setup.xml url for given device.""" return 'http://{}:{}/setup.xml'.format(device.host, device.port) def setup_url_for_address(host, port): """Determine setup.xml url for given host and port pair.""" if not port: port = pywemo.ouimeaux_device.probe_wemo(host) if not port: return None return 'http://{}:{}/setup.xml'.format(host, port) def discovery_dispatch(service, discovery_info): """Dispatcher for incoming WeMo discovery events.""" # name, model, location, mac model_name = discovery_info.get('model_name') serial = discovery_info.get('serial') # Only register a device once if serial in KNOWN_DEVICES: _LOGGER.debug('Ignoring known device %s %s', service, discovery_info) return _LOGGER.debug('Discovered unique WeMo device: %s', serial) KNOWN_DEVICES.append(serial) component = WEMO_MODEL_DISPATCH.get(model_name, 'switch') discovery.load_platform(hass, component, DOMAIN, discovery_info, config) discovery.listen(hass, SERVICE_WEMO, discovery_dispatch) def discover_wemo_devices(now): """Run discovery for WeMo devices.""" _LOGGER.debug("Beginning WeMo device discovery...") _LOGGER.debug("Adding statically configured WeMo devices...") for host, port in config.get(DOMAIN, {}).get(CONF_STATIC, []): url = setup_url_for_address(host, port) if not url: _LOGGER.error( 'Unable to get description url for WeMo at: %s', '{}:{}'.format(host, port) if port else host) continue try: device = pywemo.discovery.device_from_description(url, None) except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as err: _LOGGER.error('Unable to access WeMo at %s (%s)', url, err) continue if not [d[1] for d in devices if d[1].serialnumber == device.serialnumber]: devices.append((url, device)) if config.get(DOMAIN, {}).get(CONF_DISCOVERY): _LOGGER.debug("Scanning network for WeMo devices...") for device in pywemo.discover_devices(): if not [d[1] for d in devices if d[1].serialnumber == device.serialnumber]: devices.append((setup_url_for_device(device), device)) for url, device in devices: _LOGGER.debug('Adding WeMo device at %s:%i', device.host, device.port) discovery_info = { 'model_name': device.model_name, 'serial': device.serialnumber, 'mac_address': device.mac, 'ssdp_description': url, } discovery.discover(hass, SERVICE_WEMO, discovery_info) _LOGGER.debug("WeMo device discovery has finished") hass.bus.listen_once(EVENT_HOMEASSISTANT_START, discover_wemo_devices) return True
def setup(hass, config): """Set up for Axis devices.""" hass.data[DOMAIN] = {} def _shutdown(call): """Stop the event stream on shutdown.""" for serialnumber, device in hass.data[DOMAIN].items(): _LOGGER.info("Stopping event stream for %s.", serialnumber) device.stop() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown) def axis_device_discovered(service, discovery_info): """Call when axis devices has been found.""" host = discovery_info[CONF_HOST] name = discovery_info['hostname'] serialnumber = discovery_info['properties']['macaddress'] if serialnumber not in hass.data[DOMAIN]: config_file = load_json(hass.config.path(CONFIG_FILE)) if serialnumber in config_file: # Device config previously saved to file try: device_config = DEVICE_SCHEMA(config_file[serialnumber]) device_config[CONF_HOST] = host except vol.Invalid as err: _LOGGER.error("Bad data from %s. %s", CONFIG_FILE, err) return False if not setup_device(hass, config, device_config): _LOGGER.error( "Couldn't set up %s", device_config[CONF_NAME]) else: # New device, create configuration request for UI request_configuration(hass, config, name, host, serialnumber) else: # Device already registered, but on a different IP device = hass.data[DOMAIN][serialnumber] device.config.host = host dispatcher_send(hass, DOMAIN + '_' + device.name + '_new_ip', host) # Register discovery service discovery.listen(hass, SERVICE_AXIS, axis_device_discovered) if DOMAIN in config: for device in config[DOMAIN]: device_config = config[DOMAIN][device] if CONF_NAME not in device_config: device_config[CONF_NAME] = device if not setup_device(hass, config, device_config): _LOGGER.error("Couldn't set up %s", device_config[CONF_NAME]) def vapix_service(call): """Service to send a message.""" for device in hass.data[DOMAIN].values(): if device.name == call.data[CONF_NAME]: response = device.vapix.do_request( call.data[SERVICE_CGI], call.data[SERVICE_ACTION], call.data[SERVICE_PARAM]) hass.bus.fire(SERVICE_VAPIX_CALL_RESPONSE, response) return True _LOGGER.info("Couldn't find device %s", call.data[CONF_NAME]) return False # Register service with Home Assistant. hass.services.register( DOMAIN, SERVICE_VAPIX_CALL, vapix_service, schema=SERVICE_SCHEMA) return True
def setup(hass, config): """Set up the Xiaomi component.""" gateways = [] interface = 'any' discovery_retry = 3 if DOMAIN in config: gateways = config[DOMAIN][CONF_GATEWAYS] interface = config[DOMAIN][CONF_INTERFACE] discovery_retry = config[DOMAIN][CONF_DISCOVERY_RETRY] @asyncio.coroutine def xiaomi_gw_discovered(service, discovery_info): """Perform action when Xiaomi Gateway device(s) has been found.""" # We don't need to do anything here, the purpose of Home Assistant's # discovery service is to just trigger loading of this # component, and then its own discovery process kicks in. discovery.listen(hass, SERVICE_XIAOMI_GW, xiaomi_gw_discovered) from xiaomi_gateway import XiaomiGatewayDiscovery xiaomi = hass.data[PY_XIAOMI_GATEWAY] = XiaomiGatewayDiscovery( hass.add_job, gateways, interface) _LOGGER.debug("Expecting %s gateways", len(gateways)) for k in range(discovery_retry): _LOGGER.info("Discovering Xiaomi Gateways (Try %s)", k + 1) xiaomi.discover_gateways() if len(xiaomi.gateways) >= len(gateways): break if not xiaomi.gateways: _LOGGER.error("No gateway discovered") return False xiaomi.listen() _LOGGER.debug("Gateways discovered. Listening for broadcasts") for component in ['binary_sensor', 'sensor', 'switch', 'light', 'cover']: discovery.load_platform(hass, component, DOMAIN, {}, config) def stop_xiaomi(event): """Stop Xiaomi Socket.""" _LOGGER.info("Shutting down Xiaomi Hub") xiaomi.stop_listen() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_xiaomi) def play_ringtone_service(call): """Service to play ringtone through Gateway.""" ring_id = call.data.get(ATTR_RINGTONE_ID) gateway = call.data.get(ATTR_GW_MAC) kwargs = {'mid': ring_id} ring_vol = call.data.get(ATTR_RINGTONE_VOL) if ring_vol is not None: kwargs['vol'] = ring_vol gateway.write_to_hub(gateway.sid, **kwargs) def stop_ringtone_service(call): """Service to stop playing ringtone on Gateway.""" gateway = call.data.get(ATTR_GW_MAC) gateway.write_to_hub(gateway.sid, mid=10000) def add_device_service(call): """Service to add a new sub-device within the next 30 seconds.""" gateway = call.data.get(ATTR_GW_MAC) gateway.write_to_hub(gateway.sid, join_permission='yes') hass.components.persistent_notification.async_create( 'Join permission enabled for 30 seconds! ' 'Please press the pairing button of the new device once.', title='Xiaomi Aqara Gateway') def remove_device_service(call): """Service to remove a sub-device from the gateway.""" device_id = call.data.get(ATTR_DEVICE_ID) gateway = call.data.get(ATTR_GW_MAC) gateway.write_to_hub(gateway.sid, remove_device=device_id) gateway_only_schema = _add_gateway_to_schema(xiaomi, vol.Schema({})) hass.services.async_register(DOMAIN, SERVICE_PLAY_RINGTONE, play_ringtone_service, schema=_add_gateway_to_schema( xiaomi, SERVICE_SCHEMA_PLAY_RINGTONE)) hass.services.async_register(DOMAIN, SERVICE_STOP_RINGTONE, stop_ringtone_service, schema=gateway_only_schema) hass.services.async_register(DOMAIN, SERVICE_ADD_DEVICE, add_device_service, schema=gateway_only_schema) hass.services.async_register(DOMAIN, SERVICE_REMOVE_DEVICE, remove_device_service, schema=_add_gateway_to_schema( xiaomi, SERVICE_SCHEMA_REMOVE_DEVICE)) return True
def setup(hass, config, session=None): """Set up the Telldus Live component.""" from tellduslive import Session, supports_local_api config_filename = hass.config.path(TELLLDUS_CONFIG_FILE) conf = load_json(config_filename) def request_configuration(host=None): """Request TelldusLive authorization.""" configurator = hass.components.configurator hass.data.setdefault(KEY_CONFIG, {}) data_key = host or DOMAIN # Configuration already in progress if hass.data[KEY_CONFIG].get(data_key): return _LOGGER.info('Configuring TelldusLive %s', 'local client: {}'.format(host) if host else 'cloud service') session = Session(public_key=PUBLIC_KEY, private_key=NOT_SO_PRIVATE_KEY, host=host, application=APPLICATION_NAME) auth_url = session.authorize_url if not auth_url: _LOGGER.warning('Failed to retrieve authorization URL') return _LOGGER.debug('Got authorization URL %s', auth_url) def configuration_callback(callback_data): """Handle the submitted configuration.""" session.authorize() res = setup(hass, config, session) if not res: configurator.notify_errors( hass.data[KEY_CONFIG].get(data_key), 'Unable to connect.') return conf.update( {host: {CONF_HOST: host, CONF_TOKEN: session.access_token}} if host else {DOMAIN: {CONF_TOKEN: session.access_token, CONF_TOKEN_SECRET: session.access_token_secret}}) save_json(config_filename, conf) # Close all open configurators: for now, we only support one # tellstick device, and configuration via either cloud service # or via local API, not both at the same time for instance in hass.data[KEY_CONFIG].values(): configurator.request_done(instance) hass.data[KEY_CONFIG][data_key] = \ configurator.request_config( 'TelldusLive ({})'.format( 'LocalAPI' if host else 'Cloud service'), configuration_callback, description=CONFIG_INSTRUCTIONS.format( app_name=APPLICATION_NAME, auth_url=auth_url), submit_caption='Confirm', entity_picture='/static/images/logo_tellduslive.png', ) def tellstick_discovered(service, info): """Run when a Tellstick is discovered.""" _LOGGER.info('Discovered tellstick device') if DOMAIN in hass.data: _LOGGER.debug('Tellstick already configured') return host, device = info[:2] if not supports_local_api(device): _LOGGER.debug('Tellstick does not support local API') # Configure the cloud service hass.async_add_job(request_configuration) return _LOGGER.debug('Tellstick does support local API') # Ignore any known devices if conf and host in conf: _LOGGER.debug('Discovered already known device: %s', host) return # Offer configuration of both live and local API request_configuration() request_configuration(host) discovery.listen(hass, SERVICE_TELLDUSLIVE, tellstick_discovered) if session: _LOGGER.debug('Continuing setup configured by configurator') elif conf and CONF_HOST in next(iter(conf.values())): # For now, only one local device is supported _LOGGER.debug('Using Local API pre-configured by configurator') session = Session(**next(iter(conf.values()))) elif DOMAIN in conf: _LOGGER.debug('Using TelldusLive cloud service ' 'pre-configured by configurator') session = Session(PUBLIC_KEY, NOT_SO_PRIVATE_KEY, application=APPLICATION_NAME, **conf[DOMAIN]) elif config.get(DOMAIN): _LOGGER.info('Found entry in configuration.yaml. ' 'Requesting TelldusLive cloud service configuration') request_configuration() if CONF_HOST in config.get(DOMAIN, {}): _LOGGER.info('Found TelldusLive host entry in configuration.yaml. ' 'Requesting Telldus Local API configuration') request_configuration(config.get(DOMAIN).get(CONF_HOST)) return True else: _LOGGER.info('Tellstick discovered, awaiting discovery callback') return True if not session.is_authorized: _LOGGER.error( 'Authentication Error') return False client = TelldusLiveClient(hass, config, session) hass.data[DOMAIN] = client if session: client.update() else: hass.bus.listen(EVENT_HOMEASSISTANT_START, client.update) return True
def setup(hass, config): """Setup device tracker.""" yaml_path = hass.config.path(YAML_DEVICES) conf = config.get(DOMAIN, {}) # Config can be an empty list. In that case, substitute a dict if isinstance(conf, list): conf = conf[0] if len(conf) > 0 else {} consider_home = timedelta( seconds=util.convert(conf.get(CONF_CONSIDER_HOME), int, DEFAULT_CONSIDER_HOME)) track_new = util.convert(conf.get(CONF_TRACK_NEW), bool, DEFAULT_CONF_TRACK_NEW) home_range = util.convert(conf.get(CONF_HOME_RANGE), int, DEFAULT_HOME_RANGE) devices = load_config(yaml_path, hass, consider_home, home_range) tracker = DeviceTracker(hass, consider_home, track_new, home_range, devices) def setup_platform(p_type, p_config, disc_info=None): """Setup a device tracker platform.""" platform = prepare_setup_platform(hass, config, DOMAIN, p_type) if platform is None: return try: if hasattr(platform, 'get_scanner'): scanner = platform.get_scanner(hass, {DOMAIN: p_config}) if scanner is None: _LOGGER.error('Error setting up platform %s', p_type) return setup_scanner_platform(hass, p_config, scanner, tracker.see) return if not platform.setup_scanner(hass, p_config, tracker.see): _LOGGER.error('Error setting up platform %s', p_type) except Exception: # pylint: disable=broad-except _LOGGER.exception('Error setting up platform %s', p_type) for p_type, p_config in config_per_platform(config, DOMAIN): setup_platform(p_type, p_config) def device_tracker_discovered(service, info): """Called when a device tracker platform is discovered.""" setup_platform(DISCOVERY_PLATFORMS[service], {}, info) discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), device_tracker_discovered) def update_stale(now): """Clean up stale devices.""" tracker.update_stale(now) track_utc_time_change(hass, update_stale, second=range(0, 60, 5)) tracker.setup_group() def see_service(call): """Service to see a device.""" args = {key: value for key, value in call.data.items() if key in (ATTR_MAC, ATTR_DEV_ID, ATTR_HOST_NAME, ATTR_LOCATION_NAME, ATTR_GPS, ATTR_GPS_ACCURACY, ATTR_BATTERY)} tracker.see(**args) descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) hass.services.register(DOMAIN, SERVICE_SEE, see_service, descriptions.get(SERVICE_SEE)) return True
def setup(hass, config): """Set up the Xiaomi component.""" gateways = [] interface = 'any' discovery_retry = 3 if DOMAIN in config: gateways = config[DOMAIN][CONF_GATEWAYS] interface = config[DOMAIN][CONF_INTERFACE] discovery_retry = config[DOMAIN][CONF_DISCOVERY_RETRY] def xiaomi_gw_discovered(service, discovery_info): """Called when Xiaomi Gateway device(s) has been found.""" # We don't need to do anything here, the purpose of HA's # discovery service is to just trigger loading of this # component, and then its own discovery process kicks in. _LOGGER.info("Discovered: %s", discovery_info) discovery.listen(hass, SERVICE_XIAOMI_GW, xiaomi_gw_discovered) from PyXiaomiGateway import PyXiaomiGateway hass.data[PY_XIAOMI_GATEWAY] = PyXiaomiGateway(hass.add_job, gateways, interface) _LOGGER.debug("Expecting %s gateways", len(gateways)) for k in range(discovery_retry): _LOGGER.info('Discovering Xiaomi Gateways (Try %s)', k + 1) hass.data[PY_XIAOMI_GATEWAY].discover_gateways() if len(hass.data[PY_XIAOMI_GATEWAY].gateways) >= len(gateways): break if not hass.data[PY_XIAOMI_GATEWAY].gateways: _LOGGER.error("No gateway discovered") return False hass.data[PY_XIAOMI_GATEWAY].listen() _LOGGER.debug("Gateways discovered. Listening for broadcasts") for component in ['binary_sensor', 'sensor', 'switch', 'light', 'cover']: discovery.load_platform(hass, component, DOMAIN, {}, config) def stop_xiaomi(event): """Stop Xiaomi Socket.""" _LOGGER.info("Shutting down Xiaomi Hub.") hass.data[PY_XIAOMI_GATEWAY].stop_listen() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_xiaomi) def play_ringtone_service(call): """Service to play ringtone through Gateway.""" ring_id = call.data.get(ATTR_RINGTONE_ID) gw_sid = call.data.get(ATTR_GW_MAC) if ring_id is None or gw_sid is None: _LOGGER.error("Mandatory parameters is not specified.") return ring_id = int(ring_id) if ring_id in [9, 14 - 19]: _LOGGER.error('Specified mid: %s is not defined in gateway.', ring_id) return ring_vol = call.data.get(ATTR_RINGTONE_VOL) if ring_vol is None: ringtone = {'mid': ring_id} else: ringtone = {'mid': ring_id, 'vol': int(ring_vol)} gw_sid = gw_sid.replace(":", "").lower() for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): if gateway.sid == gw_sid: gateway.write_to_hub(gateway.sid, **ringtone) break else: _LOGGER.error('Unknown gateway sid: %s was specified.', gw_sid) def stop_ringtone_service(call): """Service to stop playing ringtone on Gateway.""" gw_sid = call.data.get(ATTR_GW_MAC) if gw_sid is None: _LOGGER.error("Mandatory parameter (%s) is not specified.", ATTR_GW_MAC) return gw_sid = gw_sid.replace(":", "").lower() for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): if gateway.sid == gw_sid: ringtone = {'mid': 10000} gateway.write_to_hub(gateway.sid, **ringtone) break else: _LOGGER.error('Unknown gateway sid: %s was specified.', gw_sid) hass.services.async_register(DOMAIN, 'play_ringtone', play_ringtone_service, description=None, schema=None) hass.services.async_register(DOMAIN, 'stop_ringtone', stop_ringtone_service, description=None, schema=None) return True
def setup(hass, config): """Set up the Xiaomi component.""" gateways = [] interface = 'any' discovery_retry = 3 if DOMAIN in config: gateways = config[DOMAIN][CONF_GATEWAYS] interface = config[DOMAIN][CONF_INTERFACE] discovery_retry = config[DOMAIN][CONF_DISCOVERY_RETRY] def xiaomi_gw_discovered(service, discovery_info): """Called when Xiaomi Gateway device(s) has been found.""" # We don't need to do anything here, the purpose of HA's # discovery service is to just trigger loading of this # component, and then its own discovery process kicks in. _LOGGER.info("Discovered: %s", discovery_info) discovery.listen(hass, SERVICE_XIAOMI_GW, xiaomi_gw_discovered) from PyXiaomiGateway import PyXiaomiGateway hass.data[PY_XIAOMI_GATEWAY] = PyXiaomiGateway(hass.add_job, gateways, interface) _LOGGER.debug("Expecting %s gateways", len(gateways)) for k in range(discovery_retry): _LOGGER.info('Discovering Xiaomi Gateways (Try %s)', k + 1) hass.data[PY_XIAOMI_GATEWAY].discover_gateways() if len(hass.data[PY_XIAOMI_GATEWAY].gateways) >= len(gateways): break if not hass.data[PY_XIAOMI_GATEWAY].gateways: _LOGGER.error("No gateway discovered") return False hass.data[PY_XIAOMI_GATEWAY].listen() _LOGGER.debug("Gateways discovered. Listening for broadcasts") for component in ['binary_sensor', 'sensor', 'switch', 'light', 'cover']: discovery.load_platform(hass, component, DOMAIN, {}, config) def stop_xiaomi(event): """Stop Xiaomi Socket.""" _LOGGER.info("Shutting down Xiaomi Hub.") hass.data[PY_XIAOMI_GATEWAY].stop_listen() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_xiaomi) def play_ringtone_service(call): """Service to play ringtone through Gateway.""" ring_id = call.data.get(ATTR_RINGTONE_ID) gw_sid = call.data.get(ATTR_GW_MAC) if ring_id is None or gw_sid is None: _LOGGER.error("Mandatory parameters is not specified.") return ring_id = int(ring_id) if ring_id in [9, 14-19]: _LOGGER.error('Specified mid: %s is not defined in gateway.', ring_id) return ring_vol = call.data.get(ATTR_RINGTONE_VOL) if ring_vol is None: ringtone = {'mid': ring_id} else: ringtone = {'mid': ring_id, 'vol': int(ring_vol)} gw_sid = gw_sid.replace(":", "").lower() for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): if gateway.sid == gw_sid: gateway.write_to_hub(gateway.sid, **ringtone) break else: _LOGGER.error('Unknown gateway sid: %s was specified.', gw_sid) def stop_ringtone_service(call): """Service to stop playing ringtone on Gateway.""" gw_sid = call.data.get(ATTR_GW_MAC) if gw_sid is None: _LOGGER.error("Mandatory parameter (%s) is not specified.", ATTR_GW_MAC) return gw_sid = gw_sid.replace(":", "").lower() for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): if gateway.sid == gw_sid: ringtone = {'mid': 10000} gateway.write_to_hub(gateway.sid, **ringtone) break else: _LOGGER.error('Unknown gateway sid: %s was specified.', gw_sid) hass.services.async_register(DOMAIN, 'play_ringtone', play_ringtone_service, description=None, schema=None) hass.services.async_register(DOMAIN, 'stop_ringtone', stop_ringtone_service, description=None, schema=None) return True