예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
    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]
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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
예제 #8
0
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
예제 #9
0
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
예제 #10
0
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
예제 #11
0
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
예제 #12
0
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
예제 #13
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
예제 #14
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
예제 #15
0
파일: wemo.py 프로젝트: masomel/py-iot-apps
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
예제 #16
0
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
예제 #17
0
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
예제 #18
0
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
예제 #19
0
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
예제 #20
0
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
예제 #21
0
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
예제 #22
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
예제 #23
0
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
예제 #24
0
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
예제 #25
0
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
예제 #26
0
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
예제 #27
0
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
예제 #28
0
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
예제 #29
0
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
예제 #30
0
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
예제 #31
0
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
예제 #32
0
    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
예제 #33
0
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
예제 #34
0
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
예제 #35
0
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
예제 #36
0
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
예제 #37
0
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
예제 #38
0
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
예제 #39
0
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
예제 #40
0
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
예제 #41
0
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