Exemplo n.º 1
0
def validate_device_has_at_least_one_identifier(value: ConfigType) -> \
        ConfigType:
    """Validate that a device info entry has at least one identifying value."""
    if not value.get(CONF_IDENTIFIERS) and not value.get(CONF_CONNECTIONS):
        raise vol.Invalid("Device must have at least one identifying value in "
                          "'identifiers' and/or 'connections'")
    return value
Exemplo n.º 2
0
async def async_setup_platform(hass: HomeAssistantType, config: ConfigType,
                               async_add_devices, discovery_info=None):
    """Set up the WUnderground sensor."""
    latitude = config.get(CONF_LATITUDE, hass.config.latitude)
    longitude = config.get(CONF_LONGITUDE, hass.config.longitude)
    pws_id = config.get(CONF_PWS_ID)

    rest = WUndergroundData(
        hass, config.get(CONF_API_KEY), pws_id,
        config.get(CONF_LANG), latitude, longitude)

    if pws_id is None:
        unique_id_base = "@{:06f},{:06f}".format(longitude, latitude)
    else:
        # Manually specified weather station, use that for unique_id
        unique_id_base = pws_id
    sensors = []
    for variable in config[CONF_MONITORED_CONDITIONS]:
        sensors.append(WUndergroundSensor(hass, rest, variable,
                                          unique_id_base))

    await rest.async_update()
    if not rest.data:
        raise PlatformNotReady

    async_add_devices(sensors, True)
Exemplo n.º 3
0
async def async_setup_platform(hass: HomeAssistantType, config: ConfigType,
                               async_add_devices, discovery_info=None):
    """Set up the cast platform."""
    import pychromecast

    # Import CEC IGNORE attributes
    pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, [])
    hass.data.setdefault(ADDED_CAST_DEVICES_KEY, {})
    hass.data.setdefault(KNOWN_CHROMECASTS_KEY, {})

    # None -> use discovery; (host, port) -> manually specify chromecast.
    want_host = None
    if discovery_info:
        want_host = (discovery_info.get('host'), discovery_info.get('port'))
    elif CONF_HOST in config:
        want_host = (config.get(CONF_HOST), DEFAULT_PORT)

    enable_discovery = False
    if want_host is None:
        # We were explicitly told to enable pychromecast discovery.
        enable_discovery = True
    elif want_host[1] != DEFAULT_PORT:
        # We're trying to add a group, so we have to use pychromecast's
        # discovery to get the correct friendly name.
        enable_discovery = True

    if enable_discovery:
        @callback
        def async_cast_discovered(chromecast):
            """Callback for when a new chromecast is discovered."""
            if want_host is not None and \
                    (chromecast.host, chromecast.port) != want_host:
                return  # for groups, only add requested device
            cast_device = _async_create_cast_device(hass, chromecast)

            if cast_device is not None:
                async_add_devices([cast_device])

        async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED,
                                 async_cast_discovered)
        # Re-play the callback for all past chromecasts, store the objects in
        # a list to avoid concurrent modification resulting in exception.
        for chromecast in list(hass.data[KNOWN_CHROMECASTS_KEY].values()):
            async_cast_discovered(chromecast)

        hass.async_add_job(_setup_internal_discovery, hass)
    else:
        # Manually add a "normal" Chromecast, we can do that without discovery.
        try:
            chromecast = await hass.async_add_job(
                pychromecast.Chromecast, *want_host)
        except pychromecast.ChromecastConnectionError as err:
            _LOGGER.warning("Can't set up chromecast on %s: %s",
                            want_host[0], err)
            raise PlatformNotReady
        key = (chromecast.host, chromecast.port, chromecast.uuid)
        cast_device = _async_create_cast_device(hass, chromecast)
        if cast_device is not None:
            hass.data[KNOWN_CHROMECASTS_KEY][key] = chromecast
            async_add_devices([cast_device])
Exemplo n.º 4
0
def setup_platform(hass, config: ConfigType,
                   add_devices: Callable[[list], None], discovery_info=None):
    """Set up the Sesame platform."""
    import pysesame

    email = config.get(CONF_EMAIL)
    password = config.get(CONF_PASSWORD)

    add_devices([SesameDevice(sesame) for
                 sesame in pysesame.get_sesames(email, password)])
Exemplo n.º 5
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Start the MQTT protocol service."""
    conf = config.get(DOMAIN)  # type: Optional[ConfigType]

    # We need this because discovery can cause components to be set up and
    # otherwise it will not load the users config.
    # This needs a better solution.
    hass.data[DATA_MQTT_HASS_CONFIG] = config

    if conf is None:
        # If we have a config entry, setup is done by that config entry.
        # If there is no config entry, this should fail.
        return bool(hass.config_entries.async_entries(DOMAIN))

    conf = dict(conf)

    if CONF_EMBEDDED in conf or CONF_BROKER not in conf:
        if (conf.get(CONF_PASSWORD) is None and
                config.get('http', {}).get('api_password') is not None):
            _LOGGER.error(
                "Starting from release 0.76, the embedded MQTT broker does not"
                " use api_password as default password anymore. Please set"
                " password configuration. See https://home-assistant.io/docs/"
                "mqtt/broker#embedded-broker for details")
            return False

        broker_config = await _async_setup_server(hass, config)

        if broker_config is None:
            _LOGGER.error("Unable to start embedded MQTT broker")
            return False

        conf.update({
            CONF_BROKER: broker_config[0],
            CONF_PORT: broker_config[1],
            CONF_USERNAME: broker_config[2],
            CONF_PASSWORD: broker_config[3],
            CONF_CERTIFICATE: broker_config[4],
            CONF_PROTOCOL: broker_config[5],
            CONF_CLIENT_KEY: None,
            CONF_CLIENT_CERT: None,
            CONF_TLS_INSECURE: None,
        })

    hass.data[DATA_MQTT_CONFIG] = conf

    # Only import if we haven't before.
    if not hass.config_entries.async_entries(DOMAIN):
        hass.async_create_task(hass.config_entries.flow.async_init(
            DOMAIN, context={'source': config_entries.SOURCE_IMPORT},
            data={}
        ))

    return True
Exemplo n.º 6
0
def from_config(config: ConfigType, config_validation: bool=True):
    """Turn a condition configuration into a method."""
    factory = getattr(
        sys.modules[__name__],
        FROM_CONFIG_FORMAT.format(config.get(CONF_CONDITION)), None)

    if factory is None:
        raise HomeAssistantError('Invalid condition "{}" specified {}'.format(
            config.get(CONF_CONDITION), config))

    return factory(config, config_validation)
Exemplo n.º 7
0
def zone_from_config(config: ConfigType,
                     config_validation: bool = True) -> Callable[..., bool]:
    """Wrap action method with zone based condition."""
    if config_validation:
        config = cv.ZONE_CONDITION_SCHEMA(config)
    entity_id = config.get(CONF_ENTITY_ID)
    zone_entity_id = config.get(CONF_ZONE)

    def if_in_zone(hass: HomeAssistant,
                   variables: TemplateVarsType = None) -> bool:
        """Test if condition."""
        return zone(hass, zone_entity_id, entity_id)

    return if_in_zone
Exemplo n.º 8
0
def state_from_config(config: ConfigType,
                      config_validation: bool = True) -> Callable[..., bool]:
    """Wrap action method with state based condition."""
    if config_validation:
        config = cv.STATE_CONDITION_SCHEMA(config)
    entity_id = config.get(CONF_ENTITY_ID)
    req_state = cast(str, config.get(CONF_STATE))
    for_period = config.get('for')

    def if_state(hass: HomeAssistant,
                 variables: TemplateVarsType = None) -> bool:
        """Test if condition."""
        return state(hass, entity_id, req_state, for_period)

    return if_state
Exemplo n.º 9
0
def async_from_config(config: ConfigType, config_validation: bool = True):
    """Turn a condition configuration into a method.

    Should be run on the event loop.
    """
    for fmt in (ASYNC_FROM_CONFIG_FORMAT, FROM_CONFIG_FORMAT):
        factory = getattr(sys.modules[__name__], fmt.format(config.get(CONF_CONDITION)), None)

        if factory:
            break

    if factory is None:
        raise HomeAssistantError('Invalid condition "{}" specified {}'.format(config.get(CONF_CONDITION), config))

    return factory(config, config_validation)
Exemplo n.º 10
0
def time_from_config(config: ConfigType,
                     config_validation: bool = True) -> Callable[..., bool]:
    """Wrap action method with time based condition."""
    if config_validation:
        config = cv.TIME_CONDITION_SCHEMA(config)
    before = config.get(CONF_BEFORE)
    after = config.get(CONF_AFTER)
    weekday = config.get(CONF_WEEKDAY)

    def time_if(hass: HomeAssistant,
                variables: TemplateVarsType = None) -> bool:
        """Validate time based if-condition."""
        return time(before, after, weekday)

    return time_if
Exemplo n.º 11
0
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the recorder."""
    conf = config.get(DOMAIN, {})
    keep_days = conf.get(CONF_PURGE_KEEP_DAYS)
    purge_interval = conf.get(CONF_PURGE_INTERVAL)

    if keep_days is None and purge_interval != 0:
        _LOGGER.warning(
            "From version 0.64.0 the 'recorder' component will by default "
            "purge data older than 10 days. To keep data longer you must "
            "configure 'purge_keep_days' or 'purge_interval'.")

    db_url = conf.get(CONF_DB_URL, None)
    if not db_url:
        db_url = DEFAULT_URL.format(
            hass_config_path=hass.config.path(DEFAULT_DB_FILE))

    include = conf.get(CONF_INCLUDE, {})
    exclude = conf.get(CONF_EXCLUDE, {})
    instance = hass.data[DATA_INSTANCE] = Recorder(
        hass=hass, keep_days=keep_days, purge_interval=purge_interval,
        uri=db_url, include=include, exclude=exclude)
    instance.async_initialize()
    instance.start()

    @asyncio.coroutine
    def async_handle_purge_service(service):
        """Handle calls to the purge service."""
        instance.do_adhoc_purge(service.data[ATTR_KEEP_DAYS])

    hass.services.async_register(
        DOMAIN, SERVICE_PURGE, async_handle_purge_service,
        schema=SERVICE_PURGE_SCHEMA)

    return (yield from instance.async_db_ready)
Exemplo n.º 12
0
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType,
                                 scanner: Any, async_see_device: Callable):
    """Helper method to connect scanner-based platform to device tracker.

    This method is a coroutine.
    """
    interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)

    # Initial scan of each mac we also tell about host name for config
    seen = set()  # type: Any

    def device_tracker_scan(now: dt_util.dt.datetime):
        """Called when interval matches."""
        found_devices = scanner.scan_devices()

        for mac in found_devices:
            if mac in seen:
                host_name = None
            else:
                host_name = scanner.get_device_name(mac)
                seen.add(mac)
            hass.add_job(async_see_device(mac=mac, host_name=host_name))

    async_track_utc_time_change(
        hass, device_tracker_scan, second=range(0, 60, interval))

    hass.async_add_job(device_tracker_scan, None)
Exemplo n.º 13
0
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the recorder."""
    conf = config.get(DOMAIN, {})
    keep_days = conf.get(CONF_PURGE_KEEP_DAYS)
    purge_interval = conf.get(CONF_PURGE_INTERVAL)

    db_url = conf.get(CONF_DB_URL, None)
    if not db_url:
        db_url = DEFAULT_URL.format(
            hass_config_path=hass.config.path(DEFAULT_DB_FILE))

    include = conf.get(CONF_INCLUDE, {})
    exclude = conf.get(CONF_EXCLUDE, {})
    instance = hass.data[DATA_INSTANCE] = Recorder(
        hass=hass, keep_days=keep_days, purge_interval=purge_interval,
        uri=db_url, include=include, exclude=exclude)
    instance.async_initialize()
    instance.start()

    @asyncio.coroutine
    def async_handle_purge_service(service):
        """Handle calls to the purge service."""
        instance.do_adhoc_purge(service.data[ATTR_KEEP_DAYS])

    hass.services.async_register(
        DOMAIN, SERVICE_PURGE, async_handle_purge_service,
        schema=SERVICE_PURGE_SCHEMA)

    return (yield from instance.async_db_ready)
Exemplo n.º 14
0
def sun_from_config(config: ConfigType,
                    config_validation: bool = True) -> Callable[..., bool]:
    """Wrap action method with sun based condition."""
    if config_validation:
        config = cv.SUN_CONDITION_SCHEMA(config)
    before = config.get('before')
    after = config.get('after')
    before_offset = config.get('before_offset')
    after_offset = config.get('after_offset')

    def time_if(hass: HomeAssistant,
                variables: TemplateVarsType = None) -> bool:
        """Validate time based if-condition."""
        return sun(hass, before, after, before_offset, after_offset)

    return time_if
Exemplo n.º 15
0
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType,
                                 scanner: Any, async_see_device: Callable,
                                 platform: str):
    """Set up the connect scanner-based platform to device tracker.

    This method must be run in the event loop.
    """
    interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
    update_lock = asyncio.Lock(loop=hass.loop)
    scanner.hass = hass

    # Initial scan of each mac we also tell about host name for config
    seen = set()  # type: Any

    @asyncio.coroutine
    def async_device_tracker_scan(now: dt_util.dt.datetime):
        """Handle interval matches."""
        if update_lock.locked():
            _LOGGER.warning(
                "Updating device list from %s took longer than the scheduled "
                "scan interval %s", platform, interval)
            return

        with (yield from update_lock):
            found_devices = yield from scanner.async_scan_devices()

        for mac in found_devices:
            if mac in seen:
                host_name = None
            else:
                host_name = yield from scanner.async_get_device_name(mac)
                seen.add(mac)

            try:
                extra_attributes = (yield from
                                    scanner.async_get_extra_attributes(mac))
            except NotImplementedError:
                extra_attributes = dict()

            kwargs = {
                'mac': mac,
                'host_name': host_name,
                'source_type': SOURCE_TYPE_ROUTER,
                'attributes': {
                    'scanner': scanner.__class__.__name__,
                    **extra_attributes
                }
            }

            zone_home = hass.states.get(zone.ENTITY_ID_HOME)
            if zone_home:
                kwargs['gps'] = [zone_home.attributes[ATTR_LATITUDE],
                                 zone_home.attributes[ATTR_LONGITUDE]]
                kwargs['gps_accuracy'] = 0

            hass.async_add_job(async_see_device(**kwargs))

    async_track_time_interval(hass, async_device_tracker_scan, interval)
    hass.async_add_job(async_device_tracker_scan(None))
Exemplo n.º 16
0
async def async_setup(hass: HomeAssistantType, config: ConfigType):
    """Set up UPnP component."""
    conf_default = CONFIG_SCHEMA({DOMAIN: {}})[DOMAIN]
    conf = config.get(DOMAIN, conf_default)
    local_ip = await hass.async_add_executor_job(get_local_ip)
    hass.data[DOMAIN] = {
        'config': conf,
        'devices': {},
        'local_ip': config.get(CONF_LOCAL_IP, local_ip),
        'ports': conf.get('ports', {}),
    }

    if conf is not None:
        hass.async_create_task(hass.config_entries.flow.async_init(
            DOMAIN, context={'source': config_entries.SOURCE_IMPORT}))

    return True
Exemplo n.º 17
0
def setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the ISY 994 platform."""
    hass.data[ISY994_NODES] = {}
    for domain in SUPPORTED_DOMAINS:
        hass.data[ISY994_NODES][domain] = []

    hass.data[ISY994_WEATHER] = []

    hass.data[ISY994_PROGRAMS] = {}
    for domain in SUPPORTED_DOMAINS:
        hass.data[ISY994_PROGRAMS][domain] = []

    isy_config = config.get(DOMAIN)

    user = isy_config.get(CONF_USERNAME)
    password = isy_config.get(CONF_PASSWORD)
    tls_version = isy_config.get(CONF_TLS_VER)
    host = urlparse(isy_config.get(CONF_HOST))
    ignore_identifier = isy_config.get(CONF_IGNORE_STRING)
    sensor_identifier = isy_config.get(CONF_SENSOR_STRING)
    enable_climate = isy_config.get(CONF_ENABLE_CLIMATE)

    if host.scheme == 'http':
        https = False
        port = host.port or 80
    elif host.scheme == 'https':
        https = True
        port = host.port or 443
    else:
        _LOGGER.error("isy994 host value in configuration is invalid")
        return False

    import PyISY
    # Connect to ISY controller.
    isy = PyISY.ISY(host.hostname, port, username=user, password=password,
                    use_https=https, tls_ver=tls_version, log=_LOGGER)
    if not isy.connected:
        return False

    _categorize_nodes(hass, isy.nodes, ignore_identifier, sensor_identifier)
    _categorize_programs(hass, isy.programs)

    if enable_climate and isy.configuration.get('Weather Information'):
        _categorize_weather(hass, isy.climate)

    def stop(event: object) -> None:
        """Stop ISY auto updates."""
        isy.auto_update = False

    # Listen for HA stop to disconnect.
    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop)

    # Load platforms for the devices in the ISY controller that we support.
    for component in SUPPORTED_DOMAINS:
        discovery.load_platform(hass, component, DOMAIN, {}, config)

    isy.auto_update = True
    return True
Exemplo n.º 18
0
def setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the ISY 994 platform."""
    isy_config = config.get(DOMAIN)

    user = isy_config.get(CONF_USERNAME)
    password = isy_config.get(CONF_PASSWORD)
    tls_version = isy_config.get(CONF_TLS_VER)
    host = urlparse(isy_config.get(CONF_HOST))
    port = host.port
    addr = host.geturl()
    hidden_identifier = isy_config.get(
        CONF_HIDDEN_STRING, DEFAULT_HIDDEN_STRING)
    sensor_identifier = isy_config.get(
        CONF_SENSOR_STRING, DEFAULT_SENSOR_STRING)

    global HIDDEN_STRING
    HIDDEN_STRING = hidden_identifier

    if host.scheme == 'http':
        addr = addr.replace('http://', '')
        https = False
    elif host.scheme == 'https':
        addr = addr.replace('https://', '')
        https = True
    else:
        _LOGGER.error("isy994 host value in configuration is invalid")
        return False

    addr = addr.replace(':{}'.format(port), '')

    import PyISY

    global PYISY
    PYISY = PyISY

    # Connect to ISY controller.
    global ISY
    ISY = PyISY.ISY(addr, port, username=user, password=password,
                    use_https=https, tls_ver=tls_version, log=_LOGGER)
    if not ISY.connected:
        return False

    _categorize_nodes(hidden_identifier, sensor_identifier)

    _categorize_programs()

    if ISY.configuration.get('Weather Information'):
        _categorize_weather()

    # Listen for HA stop to disconnect.
    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop)

    # Load platforms for the devices in the ISY controller that we support.
    for component in SUPPORTED_DOMAINS:
        discovery.load_platform(hass, component, DOMAIN, {}, config)

    ISY.auto_update = True
    return True
Exemplo n.º 19
0
def async_setup_platform(hass: HomeAssistantType, config: ConfigType,
                         async_add_devices, discovery_info=None):
    """Set up the WUnderground sensor."""
    latitude = config.get(CONF_LATITUDE, hass.config.latitude)
    longitude = config.get(CONF_LONGITUDE, hass.config.longitude)

    rest = WUndergroundData(
        hass, config.get(CONF_API_KEY), config.get(CONF_PWS_ID),
        config.get(CONF_LANG), latitude, longitude)
    sensors = []
    for variable in config[CONF_MONITORED_CONDITIONS]:
        sensors.append(WUndergroundSensor(hass, rest, variable))

    yield from rest.async_update()
    if not rest.data:
        raise PlatformNotReady

    async_add_devices(sensors, True)
Exemplo n.º 20
0
def setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Setup the recorder."""
    global _INSTANCE  # pylint: disable=global-statement

    if _INSTANCE is not None:
        _LOGGER.error('Only a single instance allowed.')
        return False

    purge_days = config.get(DOMAIN, {}).get(CONF_PURGE_DAYS)

    db_url = config.get(DOMAIN, {}).get(CONF_DB_URL, None)
    if not db_url:
        db_url = DEFAULT_URL.format(
            hass_config_path=hass.config.path(DEFAULT_DB_FILE))

    _INSTANCE = Recorder(hass, purge_days=purge_days, uri=db_url)

    return True
Exemplo n.º 21
0
def async_numeric_state_from_config(config: ConfigType,
                                    config_validation: bool = True) \
                                    -> Callable[..., bool]:
    """Wrap action method with state based condition."""
    if config_validation:
        config = cv.NUMERIC_STATE_CONDITION_SCHEMA(config)
    entity_id = config.get(CONF_ENTITY_ID)
    below = config.get(CONF_BELOW)
    above = config.get(CONF_ABOVE)
    value_template = config.get(CONF_VALUE_TEMPLATE)

    def if_numeric_state(hass: HomeAssistant,
                         variables: TemplateVarsType = None) -> bool:
        """Test numeric state condition."""
        if value_template is not None:
            value_template.hass = hass

        return async_numeric_state(
            hass, entity_id, below, above, value_template, variables)

    return if_numeric_state
Exemplo n.º 22
0
def setup_platform(hass: HomeAssistantType, config: ConfigType,
                   add_entities: Callable[[list], None],
                   discovery_info: Optional[dict] = None) -> bool:
    """Set up the GTFS sensor."""
    gtfs_dir = hass.config.path(DEFAULT_PATH)
    data = str(config.get(CONF_DATA))
    origin = config.get(CONF_ORIGIN)
    destination = config.get(CONF_DESTINATION)
    name = config.get(CONF_NAME)
    offset = config.get(CONF_OFFSET)
    include_tomorrow = config.get(CONF_TOMORROW)

    if not os.path.exists(gtfs_dir):
        os.makedirs(gtfs_dir)

    if not os.path.exists(os.path.join(gtfs_dir, data)):
        _LOGGER.error("The given GTFS data file/folder was not found")
        return False

    import pygtfs

    (gtfs_root, _) = os.path.splitext(data)

    sqlite_file = "{}.sqlite?check_same_thread=False".format(gtfs_root)
    joined_path = os.path.join(gtfs_dir, sqlite_file)
    gtfs = pygtfs.Schedule(joined_path)

    # pylint: disable=no-member
    if not gtfs.feeds:
        pygtfs.append_feed(gtfs, os.path.join(gtfs_dir, data))

    add_entities([
        GTFSDepartureSensor(gtfs, name, origin, destination, offset,
                            include_tomorrow)])
    return True
Exemplo n.º 23
0
async def async_setup(hass: HomeAssistantType, config: ConfigType):
    """Set up the person component."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)
    conf_persons = config.get(DOMAIN, [])
    manager = hass.data[DOMAIN] = PersonManager(hass, component, conf_persons)
    await manager.async_initialize()

    websocket_api.async_register_command(hass, ws_list_person)
    websocket_api.async_register_command(hass, ws_create_person)
    websocket_api.async_register_command(hass, ws_update_person)
    websocket_api.async_register_command(hass, ws_delete_person)

    return True
Exemplo n.º 24
0
async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType,
                                async_add_entities, discovery_info):
    """Set up the cast platform."""
    import pychromecast

    # Import CEC IGNORE attributes
    pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, [])
    hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set())
    hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, set())

    info = None
    if discovery_info is not None:
        info = ChromecastInfo(host=discovery_info['host'],
                              port=discovery_info['port'])
    elif CONF_HOST in config:
        info = ChromecastInfo(host=config[CONF_HOST],
                              port=DEFAULT_PORT)

    @callback
    def async_cast_discovered(discover: ChromecastInfo) -> None:
        """Handle discovery of a new chromecast."""
        if info is not None and info.host_port != discover.host_port:
            # Not our requested cast device.
            return

        cast_device = _async_create_cast_device(hass, discover)
        if cast_device is not None:
            async_add_entities([cast_device])

    remove_handler = async_dispatcher_connect(
        hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered)
    # Re-play the callback for all past chromecasts, store the objects in
    # a list to avoid concurrent modification resulting in exception.
    for chromecast in list(hass.data[KNOWN_CHROMECAST_INFO_KEY]):
        async_cast_discovered(chromecast)

    if info is None or info.is_audio_group:
        # If we were a) explicitly told to enable discovery or
        # b) have an audio group cast device, we need internal discovery.
        hass.async_add_job(_setup_internal_discovery, hass)
    else:
        info = await hass.async_add_job(_fill_out_missing_chromecast_info,
                                        info)
        if info.friendly_name is None:
            _LOGGER.debug("Cannot retrieve detail information for chromecast"
                          " %s, the device may not be online", info)
            remove_handler()
            raise PlatformNotReady

        hass.async_add_job(_discover_chromecast, hass, info)
Exemplo n.º 25
0
async def _async_setup_server(hass: HomeAssistantType, config: ConfigType):
    """Try to start embedded MQTT broker.

    This method is a coroutine.
    """
    conf = config.get(DOMAIN, {})  # type: ConfigType

    success, broker_config = \
        await server.async_start(
            hass, conf.get(CONF_PASSWORD), conf.get(CONF_EMBEDDED))

    if not success:
        return None

    return broker_config
Exemplo n.º 26
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Start the MQTT protocol service."""
    conf = config.get(DOMAIN)  # type: Optional[ConfigType]

    # We need this because discovery can cause components to be set up and
    # otherwise it will not load the users config.
    # This needs a better solution.
    hass.data[DATA_MQTT_HASS_CONFIG] = config

    websocket_api.async_register_command(hass, websocket_subscribe)

    if conf is None:
        # If we have a config entry, setup is done by that config entry.
        # If there is no config entry, this should fail.
        return bool(hass.config_entries.async_entries(DOMAIN))

    conf = dict(conf)

    if CONF_EMBEDDED in conf or CONF_BROKER not in conf:

        broker_config = await _async_setup_server(hass, config)

        if broker_config is None:
            _LOGGER.error("Unable to start embedded MQTT broker")
            return False

        conf.update({
            CONF_BROKER: broker_config[0],
            CONF_PORT: broker_config[1],
            CONF_USERNAME: broker_config[2],
            CONF_PASSWORD: broker_config[3],
            CONF_CERTIFICATE: broker_config[4],
            CONF_PROTOCOL: broker_config[5],
            CONF_CLIENT_KEY: None,
            CONF_CLIENT_CERT: None,
            CONF_TLS_INSECURE: None,
        })

    hass.data[DATA_MQTT_CONFIG] = conf

    # Only import if we haven't before.
    if not hass.config_entries.async_entries(DOMAIN):
        hass.async_create_task(hass.config_entries.flow.async_init(
            DOMAIN, context={'source': config_entries.SOURCE_IMPORT},
            data={}
        ))

    return True
Exemplo n.º 27
0
def async_template_from_config(config: ConfigType,
                               config_validation: bool = True) \
                               -> Callable[..., bool]:
    """Wrap action method with state based condition."""
    if config_validation:
        config = cv.TEMPLATE_CONDITION_SCHEMA(config)
    value_template = cast(Template, config.get(CONF_VALUE_TEMPLATE))

    def template_if(hass: HomeAssistant,
                    variables: TemplateVarsType = None) -> bool:
        """Validate template based if-condition."""
        value_template.hass = hass

        return async_template(hass, value_template, variables)

    return template_if
Exemplo n.º 28
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the HomematicIP Cloud component."""
    hass.data[DOMAIN] = {}

    accesspoints = config.get(DOMAIN, [])

    for conf in accesspoints:
        if conf[CONF_ACCESSPOINT] not in configured_haps(hass):
            hass.async_add_job(hass.config_entries.flow.async_init(
                DOMAIN, context={'source': config_entries.SOURCE_IMPORT},
                data={
                    HMIPC_HAPID: conf[CONF_ACCESSPOINT],
                    HMIPC_AUTHTOKEN: conf[CONF_AUTHTOKEN],
                    HMIPC_NAME: conf[CONF_NAME],
                }
            ))

    return True
Exemplo n.º 29
0
async def _async_setup_discovery(hass: HomeAssistantType,
                                 config: ConfigType) -> bool:
    """Try to start the discovery of MQTT devices.

    This method is a coroutine.
    """
    conf = config.get(DOMAIN, {})  # type: ConfigType

    discovery = await async_prepare_setup_platform(
        hass, config, DOMAIN, 'discovery')

    if discovery is None:
        _LOGGER.error("Unable to load MQTT discovery")
        return False

    success = await discovery.async_start(
        hass, conf[CONF_DISCOVERY_PREFIX], config)  # type: bool

    return success
Exemplo n.º 30
0
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Setup the recorder."""
    conf = config.get(DOMAIN, {})
    purge_days = conf.get(CONF_PURGE_DAYS)

    db_url = conf.get(CONF_DB_URL, None)
    if not db_url:
        db_url = DEFAULT_URL.format(
            hass_config_path=hass.config.path(DEFAULT_DB_FILE))

    include = conf.get(CONF_INCLUDE, {})
    exclude = conf.get(CONF_EXCLUDE, {})
    instance = hass.data[DATA_INSTANCE] = Recorder(
        hass, purge_days=purge_days, uri=db_url, include=include,
        exclude=exclude)
    instance.async_initialize()
    instance.start()

    return (yield from instance.async_db_ready)
Exemplo n.º 31
0
def async_setup(hass: HomeAssistantType, config: ConfigType):
    """Set up the device tracker."""
    yaml_path = hass.config.path(YAML_DEVICES)

    conf = config.get(DOMAIN, [])
    conf = conf[0] if conf else {}
    consider_home = conf.get(CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME)
    track_new = conf.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW)

    devices = yield from async_load_config(yaml_path, hass, consider_home)
    tracker = DeviceTracker(hass, consider_home, track_new, devices)

    @asyncio.coroutine
    def async_setup_platform(p_type, p_config, disc_info=None):
        """Set up a device tracker platform."""
        platform = yield from async_prepare_setup_platform(
            hass, config, DOMAIN, p_type)
        if platform is None:
            return

        _LOGGER.info("Setting up %s.%s", DOMAIN, p_type)
        try:
            scanner = None
            setup = None
            if hasattr(platform, 'async_get_scanner'):
                scanner = yield from platform.async_get_scanner(
                    hass, {DOMAIN: p_config})
            elif hasattr(platform, 'get_scanner'):
                scanner = yield from hass.async_add_job(
                    platform.get_scanner, hass, {DOMAIN: p_config})
            elif hasattr(platform, 'async_setup_scanner'):
                setup = yield from platform.async_setup_scanner(
                    hass, p_config, tracker.async_see, disc_info)
            elif hasattr(platform, 'setup_scanner'):
                setup = yield from hass.async_add_job(platform.setup_scanner,
                                                      hass, p_config,
                                                      tracker.see, disc_info)
            else:
                raise HomeAssistantError("Invalid device_tracker platform.")

            if scanner:
                async_setup_scanner_platform(hass, p_config, scanner,
                                             tracker.async_see, p_type)
                return

            if not setup:
                _LOGGER.error("Error setting up platform %s", p_type)
                return

        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception("Error setting up platform %s", p_type)

    setup_tasks = [
        async_setup_platform(p_type, p_config)
        for p_type, p_config in config_per_platform(config, DOMAIN)
    ]
    if setup_tasks:
        yield from asyncio.wait(setup_tasks, loop=hass.loop)

    tracker.async_setup_group()

    @asyncio.coroutine
    def async_platform_discovered(platform, info):
        """Load a platform."""
        yield from async_setup_platform(platform, {}, disc_info=info)

    discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered)

    # Clean up stale devices
    async_track_utc_time_change(hass,
                                tracker.async_update_stale,
                                second=range(0, 60, 5))

    @asyncio.coroutine
    def async_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)
        }
        yield from tracker.async_see(**args)

    descriptions = yield from hass.async_add_job(
        load_yaml_config_file,
        os.path.join(os.path.dirname(__file__), 'services.yaml'))
    hass.services.async_register(DOMAIN, SERVICE_SEE, async_see_service,
                                 descriptions.get(SERVICE_SEE))

    # restore
    yield from tracker.async_setup_tracked_device()
    return True
Exemplo n.º 32
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up Meteo-France from legacy config file."""
    if not (conf := config.get(DOMAIN)):
        return True
Exemplo n.º 33
0
def setup_services(
    hass: HomeAssistant,
    hass_config: ConfigType,
    config: ConfigType,
    track_new_found_calendars: bool,
    calendar_service: GoogleCalendarService,
) -> None:
    """Set up the service listeners."""

    def _found_calendar(call: ServiceCall) -> None:
        """Check if we know about a calendar and generate PLATFORM_DISCOVER."""
        calendar = get_calendar_info(hass, call.data)
        if hass.data[DATA_INDEX].get(calendar[CONF_CAL_ID]) is not None:
            return

        hass.data[DATA_INDEX].update({calendar[CONF_CAL_ID]: calendar})

        update_config(
            hass.config.path(YAML_DEVICES), hass.data[DATA_INDEX][calendar[CONF_CAL_ID]]
        )

        discovery.load_platform(
            hass,
            Platform.CALENDAR,
            DOMAIN,
            hass.data[DATA_INDEX][calendar[CONF_CAL_ID]],
            hass_config,
        )

    hass.services.register(DOMAIN, SERVICE_FOUND_CALENDARS, _found_calendar)

    def _scan_for_calendars(call: ServiceCall) -> None:
        """Scan for new calendars."""
        service = calendar_service.get()
        cal_list = service.calendarList()
        calendars = cal_list.list().execute()["items"]
        for calendar in calendars:
            calendar["track"] = track_new_found_calendars
            hass.services.call(DOMAIN, SERVICE_FOUND_CALENDARS, calendar)

    hass.services.register(DOMAIN, SERVICE_SCAN_CALENDARS, _scan_for_calendars)

    def _add_event(call: ServiceCall) -> None:
        """Add a new event to calendar."""
        service = calendar_service.get()
        start = {}
        end = {}

        if EVENT_IN in call.data:
            if EVENT_IN_DAYS in call.data[EVENT_IN]:
                now = datetime.now()

                start_in = now + timedelta(days=call.data[EVENT_IN][EVENT_IN_DAYS])
                end_in = start_in + timedelta(days=1)

                start = {"date": start_in.strftime("%Y-%m-%d")}
                end = {"date": end_in.strftime("%Y-%m-%d")}

            elif EVENT_IN_WEEKS in call.data[EVENT_IN]:
                now = datetime.now()

                start_in = now + timedelta(weeks=call.data[EVENT_IN][EVENT_IN_WEEKS])
                end_in = start_in + timedelta(days=1)

                start = {"date": start_in.strftime("%Y-%m-%d")}
                end = {"date": end_in.strftime("%Y-%m-%d")}

        elif EVENT_START_DATE in call.data:
            start = {"date": str(call.data[EVENT_START_DATE])}
            end = {"date": str(call.data[EVENT_END_DATE])}

        elif EVENT_START_DATETIME in call.data:
            start_dt = str(
                call.data[EVENT_START_DATETIME].strftime("%Y-%m-%dT%H:%M:%S")
            )
            end_dt = str(call.data[EVENT_END_DATETIME].strftime("%Y-%m-%dT%H:%M:%S"))
            start = {"dateTime": start_dt, "timeZone": str(hass.config.time_zone)}
            end = {"dateTime": end_dt, "timeZone": str(hass.config.time_zone)}

        event = {
            "summary": call.data[EVENT_SUMMARY],
            "description": call.data[EVENT_DESCRIPTION],
            "start": start,
            "end": end,
        }
        service_data = {"calendarId": call.data[EVENT_CALENDAR_ID], "body": event}
        event = service.events().insert(**service_data).execute()

    # Only expose the add event service if we have the correct permissions
    if config.get(CONF_CALENDAR_ACCESS) is FeatureAccess.read_write:
        hass.services.register(
            DOMAIN, SERVICE_ADD_EVENT, _add_event, schema=ADD_EVENT_SERVICE_SCHEMA
        )
Exemplo n.º 34
0
async def async_attach_trigger(
    hass: HomeAssistant,
    config: ConfigType,
    action: AutomationActionType,
    automation_info: AutomationTriggerInfo,
    *,
    platform_type: str = "template",
) -> CALLBACK_TYPE:
    """Listen for state changes based on configuration."""
    trigger_data = automation_info["trigger_data"]
    value_template: Template = config[CONF_VALUE_TEMPLATE]
    value_template.hass = hass
    time_delta = config.get(CONF_FOR)
    template.attach(hass, time_delta)
    delay_cancel = None
    job = HassJob(action)
    armed = False

    # Arm at setup if the template is already false.
    try:
        if not result_as_boolean(
                value_template.async_render(automation_info["variables"])):
            armed = True
    except exceptions.TemplateError as ex:
        _LOGGER.warning(
            "Error initializing 'template' trigger for '%s': %s",
            automation_info["name"],
            ex,
        )

    @callback
    def template_listener(event, updates):
        """Listen for state changes and calls action."""
        nonlocal delay_cancel, armed
        result = updates.pop().result

        if isinstance(result, exceptions.TemplateError):
            _LOGGER.warning(
                "Error evaluating 'template' trigger for '%s': %s",
                automation_info["name"],
                result,
            )
            return

        if delay_cancel:
            # pylint: disable=not-callable
            delay_cancel()
            delay_cancel = None

        if not result_as_boolean(result):
            armed = True
            return

        # Only fire when previously armed.
        if not armed:
            return

        # Fire!
        armed = False

        entity_id = event and event.data.get("entity_id")
        from_s = event and event.data.get("old_state")
        to_s = event and event.data.get("new_state")

        if entity_id is not None:
            description = f"{entity_id} via template"
        else:
            description = "time change or manual update via template"

        template_variables = {
            "platform": platform_type,
            "entity_id": entity_id,
            "from_state": from_s,
            "to_state": to_s,
        }
        trigger_variables = {
            **trigger_data,
            "for": time_delta,
            "description": description,
        }

        @callback
        def call_action(*_):
            """Call action with right context."""
            nonlocal trigger_variables
            hass.async_run_hass_job(
                job,
                {"trigger": {
                    **template_variables,
                    **trigger_variables
                }},
                (to_s.context if to_s else None),
            )

        if not time_delta:
            call_action()
            return

        try:
            period = cv.positive_time_period(
                template.render_complex(time_delta,
                                        {"trigger": template_variables}))
        except (exceptions.TemplateError, vol.Invalid) as ex:
            _LOGGER.error("Error rendering '%s' for template: %s",
                          automation_info["name"], ex)
            return

        trigger_variables["for"] = period

        delay_cancel = async_call_later(hass, period.total_seconds(),
                                        call_action)

    info = async_track_template_result(
        hass,
        [TrackTemplate(value_template, automation_info["variables"])],
        template_listener,
    )
    unsub = info.async_remove

    @callback
    def async_remove():
        """Remove state listeners async."""
        unsub()
        if delay_cancel:
            # pylint: disable=not-callable
            delay_cancel()

    return async_remove
Exemplo n.º 35
0
async def async_from_config_dict(
    config: ConfigType, hass: core.HomeAssistant
) -> core.HomeAssistant | None:
    """Try to configure Home Assistant from a configuration dictionary.

    Dynamically loads required components and its dependencies.
    This method is a coroutine.
    """
    start = monotonic()

    hass.config_entries = config_entries.ConfigEntries(hass, config)
    await hass.config_entries.async_initialize()

    # Set up core.
    _LOGGER.debug("Setting up %s", CORE_INTEGRATIONS)

    if not all(
        await asyncio.gather(
            *(
                async_setup_component(hass, domain, config)
                for domain in CORE_INTEGRATIONS
            )
        )
    ):
        _LOGGER.error("Home Assistant core failed to initialize. ")
        return None

    _LOGGER.debug("Home Assistant core initialized")

    core_config = config.get(core.DOMAIN, {})

    try:
        await conf_util.async_process_ha_core_config(hass, core_config)
    except vol.Invalid as config_err:
        conf_util.async_log_exception(config_err, "homeassistant", core_config, hass)
        return None
    except HomeAssistantError:
        _LOGGER.error(
            "Home Assistant core failed to initialize. "
            "Further initialization aborted"
        )
        return None

    await _async_set_up_integrations(hass, config)

    stop = monotonic()
    _LOGGER.info("Home Assistant initialized in %.2fs", stop - start)

    if REQUIRED_NEXT_PYTHON_DATE and sys.version_info[:3] < REQUIRED_NEXT_PYTHON_VER:
        msg = (
            "Support for the running Python version "
            f"{'.'.join(str(x) for x in sys.version_info[:3])} is deprecated and will "
            f"be removed in the first release after {REQUIRED_NEXT_PYTHON_DATE}. "
            "Please upgrade Python to "
            f"{'.'.join(str(x) for x in REQUIRED_NEXT_PYTHON_VER)} or "
            "higher."
        )
        _LOGGER.warning(msg)
        hass.components.persistent_notification.async_create(
            msg, "Python version", "python_version"
        )

    return hass
Exemplo n.º 36
0
def setup_platform(
    hass: HomeAssistant,
    config: ConfigType,
    add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType | None = None,
) -> None:
    """Set up the aREST sensor."""
    resource = config[CONF_RESOURCE]
    var_conf = config[CONF_MONITORED_VARIABLES]
    pins = config[CONF_PINS]

    try:
        response = requests.get(resource, timeout=10).json()
    except requests.exceptions.MissingSchema:
        _LOGGER.error(
            "Missing resource or schema in configuration. Add http:// to your URL"
        )
        return
    except requests.exceptions.ConnectionError:
        _LOGGER.error("No route to device at %s", resource)
        return

    arest = ArestData(resource)

    def make_renderer(value_template):
        """Create a renderer based on variable_template value."""
        if value_template is None:
            return lambda value: value

        value_template.hass = hass

        def _render(value):
            try:
                return value_template.async_render({"value": value},
                                                   parse_result=False)
            except TemplateError:
                _LOGGER.exception("Error parsing value")
                return value

        return _render

    dev = []

    if var_conf is not None:
        for variable, var_data in var_conf.items():
            if variable not in response["variables"]:
                _LOGGER.error("Variable: %s does not exist", variable)
                continue

            renderer = make_renderer(var_data.get(CONF_VALUE_TEMPLATE))
            dev.append(
                ArestSensor(
                    arest,
                    resource,
                    config.get(CONF_NAME, response[CONF_NAME]),
                    var_data.get(CONF_NAME, variable),
                    variable=variable,
                    unit_of_measurement=var_data.get(CONF_UNIT_OF_MEASUREMENT),
                    renderer=renderer,
                ))

    if pins is not None:
        for pinnum, pin in pins.items():
            renderer = make_renderer(pin.get(CONF_VALUE_TEMPLATE))
            dev.append(
                ArestSensor(
                    ArestData(resource, pinnum),
                    resource,
                    config.get(CONF_NAME, response[CONF_NAME]),
                    pin.get(CONF_NAME),
                    pin=pinnum,
                    unit_of_measurement=pin.get(CONF_UNIT_OF_MEASUREMENT),
                    renderer=renderer,
                ))

    add_entities(dev, True)
Exemplo n.º 37
0
async def async_setup(hass: HomeAssistantType, config: ConfigType):
    """Set up the device tracker."""
    yaml_path = hass.config.path(YAML_DEVICES)

    conf = config.get(DOMAIN, [])
    conf = conf[0] if conf else {}
    consider_home = conf.get(CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME)

    defaults = conf.get(CONF_NEW_DEVICE_DEFAULTS, {})
    track_new = conf.get(CONF_TRACK_NEW)
    if track_new is None:
        track_new = defaults.get(CONF_TRACK_NEW, DEFAULT_TRACK_NEW)

    devices = await async_load_config(yaml_path, hass, consider_home)
    tracker = DeviceTracker(hass, consider_home, track_new, defaults, devices)

    async def async_setup_platform(p_type, p_config, disc_info=None):
        """Set up a device tracker platform."""
        platform = await async_prepare_setup_platform(hass, config, DOMAIN,
                                                      p_type)
        if platform is None:
            return

        _LOGGER.info("Setting up %s.%s", DOMAIN, p_type)
        try:
            scanner = None
            setup = None
            if hasattr(platform, 'async_get_scanner'):
                scanner = await platform.async_get_scanner(
                    hass, {DOMAIN: p_config})
            elif hasattr(platform, 'get_scanner'):
                scanner = await hass.async_add_job(platform.get_scanner, hass,
                                                   {DOMAIN: p_config})
            elif hasattr(platform, 'async_setup_scanner'):
                setup = await platform.async_setup_scanner(
                    hass, p_config, tracker.async_see, disc_info)
            elif hasattr(platform, 'setup_scanner'):
                setup = await hass.async_add_job(platform.setup_scanner, hass,
                                                 p_config, tracker.see,
                                                 disc_info)
            else:
                raise HomeAssistantError("Invalid device_tracker platform.")

            if scanner:
                async_setup_scanner_platform(hass, p_config, scanner,
                                             tracker.async_see, p_type)
                return

            if not setup:
                _LOGGER.error("Error setting up platform %s", p_type)
                return

        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception("Error setting up platform %s", p_type)

    setup_tasks = [
        async_setup_platform(p_type, p_config)
        for p_type, p_config in config_per_platform(config, DOMAIN)
    ]
    if setup_tasks:
        await asyncio.wait(setup_tasks, loop=hass.loop)

    tracker.async_setup_group()

    async def async_platform_discovered(platform, info):
        """Load a platform."""
        await async_setup_platform(platform, {}, disc_info=info)

    discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered)

    # Clean up stale devices
    async_track_utc_time_change(hass,
                                tracker.async_update_stale,
                                second=range(0, 60, 5))

    async def async_see_service(call):
        """Service to see a device."""
        # Temp workaround for iOS, introduced in 0.65
        data = dict(call.data)
        data.pop('hostname', None)
        data.pop('battery_status', None)
        await tracker.async_see(**data)

    hass.services.async_register(DOMAIN, SERVICE_SEE, async_see_service,
                                 SERVICE_SEE_PAYLOAD_SCHEMA)

    # restore
    await tracker.async_setup_tracked_device()
    return True
Exemplo n.º 38
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the demo environment."""
    if DOMAIN not in config:
        return True

    if not hass.config_entries.async_entries(DOMAIN):
        hass.async_create_task(
            hass.config_entries.flow.async_init(
                DOMAIN,
                context={"source": config_entries.SOURCE_IMPORT},
                data={}))

    # Set up demo platforms
    for platform in COMPONENTS_WITH_DEMO_PLATFORM:
        hass.async_create_task(
            hass.helpers.discovery.async_load_platform(platform, DOMAIN, {},
                                                       config))

    config.setdefault(ha.DOMAIN, {})
    config.setdefault(DOMAIN, {})

    # Set up sun
    if not hass.config.latitude:
        hass.config.latitude = 32.87336

    if not hass.config.longitude:
        hass.config.longitude = 117.22743

    tasks = [setup.async_setup_component(hass, "sun", config)]

    # Set up input select
    tasks.append(
        setup.async_setup_component(
            hass,
            "input_select",
            {
                "input_select": {
                    "living_room_preset": {
                        "options":
                        ["Visitors", "Visitors with kids", "Home Alone"]
                    },
                    "who_cooks": {
                        "icon": "mdi:panda",
                        "initial": "Anne Therese",
                        "name": "Cook today",
                        "options": ["Paulus", "Anne Therese"],
                    },
                }
            },
        ))

    # Set up input boolean
    tasks.append(
        setup.async_setup_component(
            hass,
            "input_boolean",
            {
                "input_boolean": {
                    "notify": {
                        "icon": "mdi:car",
                        "initial": False,
                        "name": "Notify Anne Therese is home",
                    }
                }
            },
        ))

    # Set up input button
    tasks.append(
        setup.async_setup_component(
            hass,
            "input_button",
            {
                "input_button": {
                    "bell": {
                        "icon": "mdi:bell-ring-outline",
                        "name": "Ring bell",
                    }
                }
            },
        ))

    # Set up input number
    tasks.append(
        setup.async_setup_component(
            hass,
            "input_number",
            {
                "input_number": {
                    "noise_allowance": {
                        "icon": "mdi:bell-ring",
                        "min": 0,
                        "max": 10,
                        "name": "Allowed Noise",
                        "unit_of_measurement": SOUND_PRESSURE_DB,
                    }
                }
            },
        ))

    results = await asyncio.gather(*tasks)

    if any(not result for result in results):
        return False

    # Set up example persistent notification
    persistent_notification.async_create(
        hass,
        "This is an example of a persistent notification.",
        title="Example Notification",
    )

    async def demo_start_listener(_event):
        """Finish set up."""
        await finish_setup(hass, config)

    hass.bus.async_listen(EVENT_HOMEASSISTANT_START, demo_start_listener)

    return True
Exemplo n.º 39
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Set up an input select."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)
    id_manager = collection.IDManager()

    yaml_collection = collection.YamlCollection(
        logging.getLogger(f"{__name__}.yaml_collection"), id_manager)
    collection.sync_entity_lifecycle(hass, DOMAIN, DOMAIN, component,
                                     yaml_collection, InputSelect.from_yaml)

    storage_collection = InputSelectStorageCollection(
        Store(hass, STORAGE_VERSION, STORAGE_KEY),
        logging.getLogger(f"{__name__}.storage_collection"),
        id_manager,
    )
    collection.sync_entity_lifecycle(hass, DOMAIN, DOMAIN, component,
                                     storage_collection, InputSelect)

    await yaml_collection.async_load([{
        CONF_ID: id_,
        **cfg
    } for id_, cfg in config.get(DOMAIN, {}).items()])
    await storage_collection.async_load()

    collection.StorageCollectionWebsocket(storage_collection, DOMAIN, DOMAIN,
                                          CREATE_FIELDS,
                                          UPDATE_FIELDS).async_setup(hass)

    async def reload_service_handler(service_call: ServiceCallType) -> None:
        """Reload yaml entities."""
        conf = await component.async_prepare_reload(skip_reset=True)
        if conf is None:
            conf = {DOMAIN: {}}
        await yaml_collection.async_load([{
            CONF_ID: id_,
            **cfg
        } for id_, cfg in conf.get(DOMAIN, {}).items()])

    homeassistant.helpers.service.async_register_admin_service(
        hass,
        DOMAIN,
        SERVICE_RELOAD,
        reload_service_handler,
        schema=RELOAD_SERVICE_SCHEMA,
    )

    component.async_register_entity_service(
        SERVICE_SELECT_OPTION,
        {vol.Required(ATTR_OPTION): cv.string},
        "async_select_option",
    )

    component.async_register_entity_service(
        SERVICE_SELECT_NEXT,
        {vol.Optional(ATTR_CYCLE, default=True): bool},
        "async_next",
    )

    component.async_register_entity_service(
        SERVICE_SELECT_PREVIOUS,
        {vol.Optional(ATTR_CYCLE, default=True): bool},
        "async_previous",
    )

    component.async_register_entity_service(
        SERVICE_SELECT_FIRST,
        {},
        callback(lambda entity, call: entity.async_select_index(0)),
    )

    component.async_register_entity_service(
        SERVICE_SELECT_LAST,
        {},
        callback(lambda entity, call: entity.async_select_index(-1)),
    )

    component.async_register_entity_service(
        SERVICE_SET_OPTIONS,
        {
            vol.Required(ATTR_OPTIONS):
            vol.All(cv.ensure_list, vol.Length(min=1), [cv.string])
        },
        "async_set_options",
    )

    return True
Exemplo n.º 40
0
def _create_light(knx_module: XKNX, config: ConfigType) -> XknxLight:
    """Return a KNX Light device to be used within XKNX."""

    group_address_tunable_white = None
    group_address_tunable_white_state = None
    group_address_color_temp = None
    group_address_color_temp_state = None
    if config[LightSchema.CONF_COLOR_TEMP_MODE] == ColorTempModes.ABSOLUTE:
        group_address_color_temp = config.get(
            LightSchema.CONF_COLOR_TEMP_ADDRESS)
        group_address_color_temp_state = config.get(
            LightSchema.CONF_COLOR_TEMP_STATE_ADDRESS)
    elif config[LightSchema.CONF_COLOR_TEMP_MODE] == ColorTempModes.RELATIVE:
        group_address_tunable_white = config.get(
            LightSchema.CONF_COLOR_TEMP_ADDRESS)
        group_address_tunable_white_state = config.get(
            LightSchema.CONF_COLOR_TEMP_STATE_ADDRESS)

    (
        red_switch,
        red_switch_state,
        red_brightness,
        red_brightness_state,
    ) = _create_light_color(LightSchema.CONF_RED, config)
    (
        green_switch,
        green_switch_state,
        green_brightness,
        green_brightness_state,
    ) = _create_light_color(LightSchema.CONF_GREEN, config)
    (
        blue_switch,
        blue_switch_state,
        blue_brightness,
        blue_brightness_state,
    ) = _create_light_color(LightSchema.CONF_BLUE, config)
    (
        white_switch,
        white_switch_state,
        white_brightness,
        white_brightness_state,
    ) = _create_light_color(LightSchema.CONF_WHITE, config)

    return XknxLight(
        knx_module,
        name=config[CONF_NAME],
        group_address_switch=config.get(CONF_ADDRESS),
        group_address_switch_state=config.get(LightSchema.CONF_STATE_ADDRESS),
        group_address_brightness=config.get(
            LightSchema.CONF_BRIGHTNESS_ADDRESS),
        group_address_brightness_state=config.get(
            LightSchema.CONF_BRIGHTNESS_STATE_ADDRESS),
        group_address_color=config.get(LightSchema.CONF_COLOR_ADDRESS),
        group_address_color_state=config.get(
            LightSchema.CONF_COLOR_STATE_ADDRESS),
        group_address_rgbw=config.get(LightSchema.CONF_RGBW_ADDRESS),
        group_address_rgbw_state=config.get(
            LightSchema.CONF_RGBW_STATE_ADDRESS),
        group_address_tunable_white=group_address_tunable_white,
        group_address_tunable_white_state=group_address_tunable_white_state,
        group_address_color_temperature=group_address_color_temp,
        group_address_color_temperature_state=group_address_color_temp_state,
        group_address_switch_red=red_switch,
        group_address_switch_red_state=red_switch_state,
        group_address_brightness_red=red_brightness,
        group_address_brightness_red_state=red_brightness_state,
        group_address_switch_green=green_switch,
        group_address_switch_green_state=green_switch_state,
        group_address_brightness_green=green_brightness,
        group_address_brightness_green_state=green_brightness_state,
        group_address_switch_blue=blue_switch,
        group_address_switch_blue_state=blue_switch_state,
        group_address_brightness_blue=blue_brightness,
        group_address_brightness_blue_state=blue_brightness_state,
        group_address_switch_white=white_switch,
        group_address_switch_white_state=white_switch_state,
        group_address_brightness_white=white_brightness,
        group_address_brightness_white_state=white_brightness_state,
        min_kelvin=config[LightSchema.CONF_MIN_KELVIN],
        max_kelvin=config[LightSchema.CONF_MAX_KELVIN],
    )
Exemplo n.º 41
0
def _create_climate(knx_module: XKNX, config: ConfigType) -> XknxClimate:
    """Return a KNX Climate device to be used within XKNX."""
    climate_mode = XknxClimateMode(
        knx_module,
        name=f"{config[CONF_NAME]} Mode",
        group_address_operation_mode=config.get(
            ClimateSchema.CONF_OPERATION_MODE_ADDRESS),
        group_address_operation_mode_state=config.get(
            ClimateSchema.CONF_OPERATION_MODE_STATE_ADDRESS),
        group_address_controller_status=config.get(
            ClimateSchema.CONF_CONTROLLER_STATUS_ADDRESS),
        group_address_controller_status_state=config.get(
            ClimateSchema.CONF_CONTROLLER_STATUS_STATE_ADDRESS),
        group_address_controller_mode=config.get(
            ClimateSchema.CONF_CONTROLLER_MODE_ADDRESS),
        group_address_controller_mode_state=config.get(
            ClimateSchema.CONF_CONTROLLER_MODE_STATE_ADDRESS),
        group_address_operation_mode_protection=config.get(
            ClimateSchema.CONF_OPERATION_MODE_FROST_PROTECTION_ADDRESS),
        group_address_operation_mode_night=config.get(
            ClimateSchema.CONF_OPERATION_MODE_NIGHT_ADDRESS),
        group_address_operation_mode_comfort=config.get(
            ClimateSchema.CONF_OPERATION_MODE_COMFORT_ADDRESS),
        group_address_operation_mode_standby=config.get(
            ClimateSchema.CONF_OPERATION_MODE_STANDBY_ADDRESS),
        group_address_heat_cool=config.get(
            ClimateSchema.CONF_HEAT_COOL_ADDRESS),
        group_address_heat_cool_state=config.get(
            ClimateSchema.CONF_HEAT_COOL_STATE_ADDRESS),
        operation_modes=config.get(ClimateSchema.CONF_OPERATION_MODES),
        controller_modes=config.get(ClimateSchema.CONF_CONTROLLER_MODES),
    )

    return XknxClimate(
        knx_module,
        name=config[CONF_NAME],
        group_address_temperature=config[
            ClimateSchema.CONF_TEMPERATURE_ADDRESS],
        group_address_target_temperature=config.get(
            ClimateSchema.CONF_TARGET_TEMPERATURE_ADDRESS),
        group_address_target_temperature_state=config[
            ClimateSchema.CONF_TARGET_TEMPERATURE_STATE_ADDRESS],
        group_address_setpoint_shift=config.get(
            ClimateSchema.CONF_SETPOINT_SHIFT_ADDRESS),
        group_address_setpoint_shift_state=config.get(
            ClimateSchema.CONF_SETPOINT_SHIFT_STATE_ADDRESS),
        setpoint_shift_mode=config[ClimateSchema.CONF_SETPOINT_SHIFT_MODE],
        setpoint_shift_max=config[ClimateSchema.CONF_SETPOINT_SHIFT_MAX],
        setpoint_shift_min=config[ClimateSchema.CONF_SETPOINT_SHIFT_MIN],
        temperature_step=config[ClimateSchema.CONF_TEMPERATURE_STEP],
        group_address_on_off=config.get(ClimateSchema.CONF_ON_OFF_ADDRESS),
        group_address_on_off_state=config.get(
            ClimateSchema.CONF_ON_OFF_STATE_ADDRESS),
        min_temp=config.get(ClimateSchema.CONF_MIN_TEMP),
        max_temp=config.get(ClimateSchema.CONF_MAX_TEMP),
        mode=climate_mode,
        on_off_invert=config[ClimateSchema.CONF_ON_OFF_INVERT],
        create_temperature_sensors=config.get(
            ClimateSchema.CONF_CREATE_TEMPERATURE_SENSORS),
    )
Exemplo n.º 42
0
async def async_attach_trigger(
    hass: HomeAssistant,
    config: ConfigType,
    action: TriggerActionType,
    trigger_info: TriggerInfo,
) -> CALLBACK_TYPE:
    """Listen for state changes based on configuration."""
    trigger_data = trigger_info["trigger_data"]
    topic = config[CONF_TOPIC]
    wanted_payload = config.get(CONF_PAYLOAD)
    value_template = config.get(CONF_VALUE_TEMPLATE)
    encoding = config[CONF_ENCODING] or None
    qos = config[CONF_QOS]
    job = HassJob(action)
    variables = None
    if trigger_info:
        variables = trigger_info.get("variables")

    template.attach(hass, wanted_payload)
    if wanted_payload:
        wanted_payload = wanted_payload.async_render(variables,
                                                     limited=True,
                                                     parse_result=False)

    template.attach(hass, topic)
    if isinstance(topic, template.Template):
        topic = topic.async_render(variables, limited=True, parse_result=False)
        topic = mqtt.util.valid_subscribe_topic(topic)

    template.attach(hass, value_template)

    @callback
    def mqtt_automation_listener(mqttmsg):
        """Listen for MQTT messages."""
        payload = mqttmsg.payload

        if value_template is not None:
            payload = value_template.async_render_with_possible_json_value(
                payload,
                error_value=None,
            )

        if wanted_payload is None or wanted_payload == payload:
            data = {
                **trigger_data,
                "platform": "mqtt",
                "topic": mqttmsg.topic,
                "payload": mqttmsg.payload,
                "qos": mqttmsg.qos,
                "description": f"mqtt topic {mqttmsg.topic}",
            }

            with suppress(ValueError):
                data["payload_json"] = json_loads(mqttmsg.payload)

            hass.async_run_hass_job(job, {"trigger": data})

    _LOGGER.debug("Attaching MQTT trigger for topic: '%s', payload: '%s'",
                  topic, wanted_payload)

    remove = await mqtt.async_subscribe(hass,
                                        topic,
                                        mqtt_automation_listener,
                                        encoding=encoding,
                                        qos=qos)
    return remove
Exemplo n.º 43
0
async def async_setup(hass: HomeAssistantType, config: ConfigType):
    """Setup the Homie service."""
    # Init
    _DEVICES = dict()
    hass.data[KEY_HOMIE_ALREADY_DISCOVERED] = dict()

    # Config
    conf = config.get(DOMAIN)
    if conf is None:
        conf = CONFIG_SCHEMA({DOMAIN: {}})[DOMAIN]
    discovery_prefix = conf.get(CONF_DISCOVERY_PREFIX)
    qos = conf.get(CONF_QOS)

    # Destroy Homie
    # async def async_destroy(event):
    #     # TODO: unsub?
    #     pass
    # hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_destroy)

    # Sart
    async def async_start():
        await mqtt.async_subscribe(hass, f'{discovery_prefix}/+/$homie',
                                   async_discover_message_received, qos)

    async def async_discover_message_received(topic: str, payload: str,
                                              msg_qos: int):
        device_match = DISCOVER_DEVICE.match(topic)

        if device_match and payload == HOMIE_SUPPORTED_VERSION:
            device_base_topic = device_match.group('prefix_topic')
            device_id = device_match.group('device_id')
            if device_id not in _DEVICES:
                device = HomieDevice(device_base_topic, device_id,
                                     async_component_ready)
                _DEVICES[device_id] = device
                await device._async_setup(hass, qos)

    async def async_component_ready(component):
        if type(component) is HomieDevice:
            await async_setup_device(component)
        if type(component) is HomieNode:
            await async_setup_node(component)

    async def async_setup_device(device: HomieDevice):
        pass

    async def async_setup_node(node: HomieNode):
        def get_entity_name():
            return f"{node.device.device_id}_{node.node_id}"

        if node.type == 'sensor':
            await setup_device_node_as_platform(get_entity_name(), node,
                                                'sensor')
        elif node.type == 'switch':
            await setup_device_node_as_platform(get_entity_name(), node,
                                                'switch')

    async def setup_device_node_as_platform(entity_name: str, node: HomieNode,
                                            platform: str):
        hass.data[KEY_HOMIE_ALREADY_DISCOVERED][entity_name] = node
        discovery_info = {KEY_HOMIE_ENTITY_NAME: entity_name}
        await async_load_platform(hass, platform, DOMAIN, discovery_info, conf)

    await async_start()
    return True
Exemplo n.º 44
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up songpal environment."""
    if (conf := config.get(DOMAIN)) is None:
        return True
Exemplo n.º 45
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Set up Huawei LTE component."""

    # dicttoxml (used by huawei-lte-api) has uselessly verbose INFO level.
    # https://github.com/quandyfactory/dicttoxml/issues/60
    logging.getLogger("dicttoxml").setLevel(logging.WARNING)

    # Arrange our YAML config to dict with normalized URLs as keys
    domain_config: dict[str, dict[str, Any]] = {}
    if DOMAIN not in hass.data:
        hass.data[DOMAIN] = HuaweiLteData(hass_config=config, config=domain_config)
    for router_config in config.get(DOMAIN, []):
        domain_config[url_normalize(router_config.pop(CONF_URL))] = router_config

    def service_handler(service: ServiceCall) -> None:
        """Apply a service."""
        url = service.data.get(CONF_URL)
        routers = hass.data[DOMAIN].routers
        if url:
            router = routers.get(url)
        elif not routers:
            _LOGGER.error("%s: no routers configured", service.service)
            return
        elif len(routers) == 1:
            router = next(iter(routers.values()))
        else:
            _LOGGER.error(
                "%s: more than one router configured, must specify one of URLs %s",
                service.service,
                sorted(routers),
            )
            return
        if not router:
            _LOGGER.error("%s: router %s unavailable", service.service, url)
            return

        if service.service == SERVICE_CLEAR_TRAFFIC_STATISTICS:
            if router.suspended:
                _LOGGER.debug("%s: ignored, integration suspended", service.service)
                return
            result = router.client.monitoring.set_clear_traffic()
            _LOGGER.debug("%s: %s", service.service, result)
        elif service.service == SERVICE_REBOOT:
            if router.suspended:
                _LOGGER.debug("%s: ignored, integration suspended", service.service)
                return
            result = router.client.device.reboot()
            _LOGGER.debug("%s: %s", service.service, result)
        elif service.service == SERVICE_RESUME_INTEGRATION:
            # Login will be handled automatically on demand
            router.suspended = False
            _LOGGER.debug("%s: %s", service.service, "done")
        elif service.service == SERVICE_SUSPEND_INTEGRATION:
            router.logout()
            router.suspended = True
            _LOGGER.debug("%s: %s", service.service, "done")
        else:
            _LOGGER.error("%s: unsupported service", service.service)

    for service in ADMIN_SERVICES:
        hass.helpers.service.async_register_admin_service(
            DOMAIN,
            service,
            service_handler,
            schema=SERVICE_SCHEMA,
        )

    for url, router_config in domain_config.items():
        hass.async_create_task(
            hass.config_entries.flow.async_init(
                DOMAIN,
                context={"source": SOURCE_IMPORT},
                data={
                    CONF_URL: url,
                    CONF_USERNAME: router_config.get(CONF_USERNAME),
                    CONF_PASSWORD: router_config.get(CONF_PASSWORD),
                },
            )
        )

    return True
Exemplo n.º 46
0
 def __init__(self, config: ConfigType) -> None:
     """Initialize a boolean input."""
     self._config = config
     self.editable = True
     self._attr_is_on = config.get(CONF_INITIAL, False)
     self._attr_unique_id = config[CONF_ID]
Exemplo n.º 47
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Configure Gammu state machine."""
    hass.data.setdefault(DOMAIN, {})
    if not (sms_config := config.get(DOMAIN, {})):
        return True
Exemplo n.º 48
0
def setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the ISY 994 platform."""
    isy_config = config.get(DOMAIN)

    user = isy_config.get(CONF_USERNAME)
    password = isy_config.get(CONF_PASSWORD)
    tls_version = isy_config.get(CONF_TLS_VER)
    host = urlparse(isy_config.get(CONF_HOST))
    port = host.port
    addr = host.geturl()
    hidden_identifier = isy_config.get(CONF_HIDDEN_STRING,
                                       DEFAULT_HIDDEN_STRING)
    sensor_identifier = isy_config.get(CONF_SENSOR_STRING,
                                       DEFAULT_SENSOR_STRING)

    global HIDDEN_STRING
    HIDDEN_STRING = hidden_identifier

    if host.scheme == 'http':
        addr = addr.replace('http://', '')
        https = False
    elif host.scheme == 'https':
        addr = addr.replace('https://', '')
        https = True
    else:
        _LOGGER.error("isy994 host value in configuration is invalid")
        return False

    addr = addr.replace(':{}'.format(port), '')

    import PyISY

    global PYISY
    PYISY = PyISY

    # Connect to ISY controller.
    global ISY
    ISY = PyISY.ISY(addr,
                    port,
                    username=user,
                    password=password,
                    use_https=https,
                    tls_ver=tls_version,
                    log=_LOGGER)
    if not ISY.connected:
        return False

    _categorize_nodes(hidden_identifier, sensor_identifier)

    _categorize_programs()

    if ISY.configuration.get('Weather Information'):
        _categorize_weather()

    # Listen for HA stop to disconnect.
    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop)

    # Load platforms for the devices in the ISY controller that we support.
    for component in SUPPORTED_DOMAINS:
        discovery.load_platform(hass, component, DOMAIN, {}, config)

    ISY.auto_update = True
    return True
Exemplo n.º 49
0
def import_lcn_config(lcn_config: ConfigType) -> list[ConfigType]:
    """Convert lcn settings from configuration.yaml to config_entries data.

    Create a list of config_entry data structures like:

    "data": {
        "host": "pchk",
        "ip_address": "192.168.2.41",
        "port": 4114,
        "username": "******",
        "password": "******"sk_num_tries: 0,
        "dim_mode: "STEPS200",
        "devices": [
            {
                "address": (0, 7, False)
                "name": "",
                "hardware_serial": -1,
                "software_serial": -1,
                "hardware_type": -1
            }, ...
        ],
        "entities": [
            {
                "address": (0, 7, False)
                "name": "Light_Output1",
                "resource": "output1",
                "domain": "light",
                "domain_data": {
                    "output": "OUTPUT1",
                    "dimmable": True,
                    "transition": 5000.0
                }
            }, ...
        ]
    }
    """
    data = {}
    for connection in lcn_config[CONF_CONNECTIONS]:
        host = {
            CONF_HOST: connection[CONF_NAME],
            CONF_IP_ADDRESS: connection[CONF_HOST],
            CONF_PORT: connection[CONF_PORT],
            CONF_USERNAME: connection[CONF_USERNAME],
            CONF_PASSWORD: connection[CONF_PASSWORD],
            CONF_SK_NUM_TRIES: connection[CONF_SK_NUM_TRIES],
            CONF_DIM_MODE: connection[CONF_DIM_MODE],
            CONF_DEVICES: [],
            CONF_ENTITIES: [],
        }
        data[connection[CONF_NAME]] = host

    for confkey, domain_config in lcn_config.items():
        if confkey == CONF_CONNECTIONS:
            continue
        domain = DOMAIN_LOOKUP[confkey]
        # loop over entities in configuration.yaml
        for domain_data in domain_config:
            # remove name and address from domain_data
            entity_name = domain_data.pop(CONF_NAME)
            address, host_name = domain_data.pop(CONF_ADDRESS)

            if host_name is None:
                host_name = DEFAULT_NAME

            # check if we have a new device config
            for device_config in data[host_name][CONF_DEVICES]:
                if address == device_config[CONF_ADDRESS]:
                    break
            else:  # create new device_config
                device_config = {
                    CONF_ADDRESS: address,
                    CONF_NAME: "",
                    CONF_HARDWARE_SERIAL: -1,
                    CONF_SOFTWARE_SERIAL: -1,
                    CONF_HARDWARE_TYPE: -1,
                }

                data[host_name][CONF_DEVICES].append(device_config)

            # insert entity config
            resource = get_resource(domain, domain_data).lower()
            for entity_config in data[host_name][CONF_ENTITIES]:
                if (address == entity_config[CONF_ADDRESS]
                        and resource == entity_config[CONF_RESOURCE]
                        and domain == entity_config[CONF_DOMAIN]):
                    break
            else:  # create new entity_config
                entity_config = {
                    CONF_ADDRESS: address,
                    CONF_NAME: entity_name,
                    CONF_RESOURCE: resource,
                    CONF_DOMAIN: domain,
                    CONF_DOMAIN_DATA: domain_data.copy(),
                }
                data[host_name][CONF_ENTITIES].append(entity_config)

    return list(data.values())
Exemplo n.º 50
0
def setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the ISY 994 platform."""
    hass.data[ISY994_NODES] = {}
    for domain in SUPPORTED_DOMAINS:
        hass.data[ISY994_NODES][domain] = []

    hass.data[ISY994_WEATHER] = []

    hass.data[ISY994_PROGRAMS] = {}
    for domain in SUPPORTED_DOMAINS:
        hass.data[ISY994_PROGRAMS][domain] = []

    isy_config = config.get(DOMAIN)

    user = isy_config.get(CONF_USERNAME)
    password = isy_config.get(CONF_PASSWORD)
    tls_version = isy_config.get(CONF_TLS_VER)
    host = urlparse(isy_config.get(CONF_HOST))
    ignore_identifier = isy_config.get(CONF_IGNORE_STRING)
    sensor_identifier = isy_config.get(CONF_SENSOR_STRING)
    enable_climate = isy_config.get(CONF_ENABLE_CLIMATE)

    if host.scheme == 'http':
        https = False
        port = host.port or 80
    elif host.scheme == 'https':
        https = True
        port = host.port or 443
    else:
        _LOGGER.error("isy994 host value in configuration is invalid")
        return False

    import PyISY
    # Connect to ISY controller.
    isy = PyISY.ISY(host.hostname,
                    port,
                    username=user,
                    password=password,
                    use_https=https,
                    tls_ver=tls_version,
                    log=_LOGGER)
    if not isy.connected:
        return False

    _categorize_nodes(hass, isy.nodes, ignore_identifier, sensor_identifier)
    _categorize_programs(hass, isy.programs)

    if enable_climate and isy.configuration.get('Weather Information'):
        _categorize_weather(hass, isy.climate)

    def stop(event: object) -> None:
        """Stop ISY auto updates."""
        isy.auto_update = False

    # Listen for HA stop to disconnect.
    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop)

    # Load platforms for the devices in the ISY controller that we support.
    for component in SUPPORTED_DOMAINS:
        discovery.load_platform(hass, component, DOMAIN, {}, config)

    isy.auto_update = True
    return True
Exemplo n.º 51
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:

    conf = config.get(DOMAIN, {})  # type: ConfigType

    if conf is None:
        # If we have a config entry, setup is done by that config entry.
        # If there is no config entry, this should fail.
        return bool(hass.config_entries.async_entries(DOMAIN))

    hass.data[DATA_AIHOME_CONFIG] = conf

    # Only import if we haven't before.
    if not hass.config_entries.async_entries(DOMAIN):
        hass.async_create_task(
            hass.config_entries.flow.async_init(
                DOMAIN,
                context={'source': config_entries.SOURCE_IMPORT},
                data={}))

    if CONF_HTTP in conf:
        if conf.get(CONF_HTTP) is None:
            conf[CONF_HTTP] = HTTP_SCHEMA({})
        hass.http.register_view(AihomeGateView(hass))
        hass.http.register_view(
            AihomeAuthView(
                hass,
                conf.get(CONF_HTTP, {}).get(CONF_HA_URL,
                                            hass.config.api.base_url)))
        global EXPIRATION
        EXPIRATION = timedelta(hours=conf.get(CONF_HTTP).get(
            CONF_EXPIRE_IN_HOURS, DEFAULT_EXPIRE_IN_HOURS))
        _LOGGER.info('[init] aihome run with "http mode"(mode 1)')
        MODE.append('http')
    if CONF_HTTP_PROXY in conf:
        if conf.get(CONF_HTTP_PROXY) is None:
            conf[CONF_HTTP_PROXY] = HTTP_PROXY({})
        _LOGGER.info('[init] aihome run with "http_proxy mode"(mode 2)')
        if CONF_SETTING not in conf:
            _LOGGER.error(
                '[init] fail to start aihome: http_proxy mode require mqtt congfiguration'
            )
            return False
        MODE.append('http_proxy')
    if CONF_SKILL in conf:
        if conf.get(CONF_SKILL) is None:
            conf[CONF_SKILL] = SKILL_SCHEMA({})
        _LOGGER.info('[init] aihome run with "skill mode"(mode 3)')
        if CONF_SETTING not in conf:
            _LOGGER.error(
                '[init] fail to start aihome: skil mode require mqtt congfiguration'
            )
            return False
        MODE.append('skill')

    aihome_util.ENTITY_KEY = conf.get(CONF_SETTING, {}).get(CONF_ENTITY_KEY)
    aihome_util.CONTEXT_AIHOME = Context(
        conf.get(CONF_SETTING, {}).get(CONF_USER_ID))

    platform = conf[CONF_PLATFORM]
    manager = hass.data[DATA_AIHOME_BIND_MANAGER] = aihome_util.BindManager(
        hass, platform)
    await manager.async_load()

    for p in platform:
        try:
            module = importlib.import_module('custom_components.{}.{}'.format(
                DOMAIN, p))
            _LOGGER.info('[init] import %s.%s', DOMAIN, p)
            HANDLER[p] = module.createHandler(hass)
        except ImportError:
            _LOGGER.error('[init] Unable to import %s.%s', DOMAIN, p)
            return False

    return True
Exemplo n.º 52
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the HTTP API and debug interface."""
    conf: ConfData | None = config.get(DOMAIN)

    if conf is None:
        conf = cast(ConfData, HTTP_SCHEMA({}))

    server_host = conf.get(CONF_SERVER_HOST)
    server_port = conf[CONF_SERVER_PORT]
    ssl_certificate = conf.get(CONF_SSL_CERTIFICATE)
    ssl_peer_certificate = conf.get(CONF_SSL_PEER_CERTIFICATE)
    ssl_key = conf.get(CONF_SSL_KEY)
    cors_origins = conf[CONF_CORS_ORIGINS]
    use_x_forwarded_for = conf.get(CONF_USE_X_FORWARDED_FOR, False)
    trusted_proxies = conf.get(CONF_TRUSTED_PROXIES) or []
    is_ban_enabled = conf[CONF_IP_BAN_ENABLED]
    login_threshold = conf[CONF_LOGIN_ATTEMPTS_THRESHOLD]
    ssl_profile = conf[CONF_SSL_PROFILE]

    server = HomeAssistantHTTP(
        hass,
        server_host=server_host,
        server_port=server_port,
        ssl_certificate=ssl_certificate,
        ssl_peer_certificate=ssl_peer_certificate,
        ssl_key=ssl_key,
        cors_origins=cors_origins,
        use_x_forwarded_for=use_x_forwarded_for,
        trusted_proxies=trusted_proxies,
        login_threshold=login_threshold,
        is_ban_enabled=is_ban_enabled,
        ssl_profile=ssl_profile,
    )

    async def stop_server(event: Event) -> None:
        """Stop the server."""
        await server.stop()

    async def start_server(*_: Any) -> None:
        """Start the server."""
        with async_start_setup(hass, ["http"]):
            hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_server)
            # We already checked it's not None.
            assert conf is not None
            await start_http_server_and_save_config(hass, dict(conf), server)

    async_when_setup_or_start(hass, "frontend", start_server)

    hass.http = server

    local_ip = await async_get_source_ip(hass)

    host = local_ip
    if server_host is not None:
        # Assume the first server host name provided as API host
        host = server_host[0]

    hass.config.api = ApiConfig(local_ip, host, server_port, ssl_certificate
                                is not None)

    return True
Exemplo n.º 53
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the HomematicIP Cloud component."""
    hass.data[DOMAIN] = {}

    accesspoints = config.get(DOMAIN, [])

    for conf in accesspoints:
        if conf[CONF_ACCESSPOINT] not in configured_haps(hass):
            hass.async_add_job(
                hass.config_entries.flow.async_init(
                    DOMAIN,
                    context={'source': config_entries.SOURCE_IMPORT},
                    data={
                        HMIPC_HAPID: conf[CONF_ACCESSPOINT],
                        HMIPC_AUTHTOKEN: conf[CONF_AUTHTOKEN],
                        HMIPC_NAME: conf[CONF_NAME],
                    }))

    async def _async_activate_eco_mode_with_duration(service):
        """Service to activate eco mode with duration."""
        duration = service.data[ATTR_DURATION]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_absence_with_duration(duration)
        else:
            for hapid in hass.data[DOMAIN]:
                home = hass.data[DOMAIN][hapid].home
                await home.activate_absence_with_duration(duration)

    hass.services.async_register(DOMAIN,
                                 SERVICE_ACTIVATE_ECO_MODE_WITH_DURATION,
                                 _async_activate_eco_mode_with_duration,
                                 schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_DURATION)

    async def _async_activate_eco_mode_with_period(service):
        """Service to activate eco mode with period."""
        endtime = service.data[ATTR_ENDTIME]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_absence_with_period(endtime)
        else:
            for hapid in hass.data[DOMAIN]:
                home = hass.data[DOMAIN][hapid].home
                await home.activate_absence_with_period(endtime)

    hass.services.async_register(DOMAIN,
                                 SERVICE_ACTIVATE_ECO_MODE_WITH_PERIOD,
                                 _async_activate_eco_mode_with_period,
                                 schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_PERIOD)

    async def _async_activate_vacation(service):
        """Service to activate vacation."""
        endtime = service.data[ATTR_ENDTIME]
        temperature = service.data[ATTR_TEMPERATURE]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_vacation(endtime, temperature)
        else:
            for hapid in hass.data[DOMAIN]:
                home = hass.data[DOMAIN][hapid].home
                await home.activate_vacation(endtime, temperature)

    hass.services.async_register(DOMAIN,
                                 SERVICE_ACTIVATE_VACATION,
                                 _async_activate_vacation,
                                 schema=SCHEMA_ACTIVATE_VACATION)

    async def _async_deactivate_eco_mode(service):
        """Service to deactivate eco mode."""
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.deactivate_absence()
        else:
            for hapid in hass.data[DOMAIN]:
                home = hass.data[DOMAIN][hapid].home
                await home.deactivate_absence()

    hass.services.async_register(DOMAIN,
                                 SERVICE_DEACTIVATE_ECO_MODE,
                                 _async_deactivate_eco_mode,
                                 schema=SCHEMA_DEACTIVATE_ECO_MODE)

    async def _async_deactivate_vacation(service):
        """Service to deactivate vacation."""
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.deactivate_vacation()
        else:
            for hapid in hass.data[DOMAIN]:
                home = hass.data[DOMAIN][hapid].home
                await home.deactivate_vacation()

    hass.services.async_register(DOMAIN,
                                 SERVICE_DEACTIVATE_VACATION,
                                 _async_deactivate_vacation,
                                 schema=SCHEMA_DEACTIVATE_VACATION)

    def _get_home(hapid: str):
        """Return a HmIP home."""
        hap = hass.data[DOMAIN][hapid]
        if hap:
            return hap.home
        return None

    return True
Exemplo n.º 54
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Set up an input select."""
    component = EntityComponent(_LOGGER, DOMAIN, hass)
    id_manager = collection.IDManager()

    yaml_collection = collection.YamlCollection(
        logging.getLogger(f"{__name__}.yaml_collection"), id_manager)
    collection.attach_entity_component_collection(component, yaml_collection,
                                                  Timer.from_yaml)

    storage_collection = TimerStorageCollection(
        Store(hass, STORAGE_VERSION, STORAGE_KEY),
        logging.getLogger(f"{__name__}.storage_collection"),
        id_manager,
    )
    collection.attach_entity_component_collection(component,
                                                  storage_collection, Timer)

    await yaml_collection.async_load([{
        CONF_ID: id_,
        **cfg
    } for id_, cfg in config.get(DOMAIN, {}).items()])
    await storage_collection.async_load()

    collection.StorageCollectionWebsocket(storage_collection, DOMAIN, DOMAIN,
                                          CREATE_FIELDS,
                                          UPDATE_FIELDS).async_setup(hass)

    collection.attach_entity_registry_cleaner(hass, DOMAIN, DOMAIN,
                                              yaml_collection)
    collection.attach_entity_registry_cleaner(hass, DOMAIN, DOMAIN,
                                              storage_collection)

    async def reload_service_handler(service_call: ServiceCallType) -> None:
        """Reload yaml entities."""
        conf = await component.async_prepare_reload(skip_reset=True)
        if conf is None:
            conf = {DOMAIN: {}}
        await yaml_collection.async_load([{
            CONF_ID: id_,
            **cfg
        } for id_, cfg in conf.get(DOMAIN, {}).items()])

    homeassistant.helpers.service.async_register_admin_service(
        hass,
        DOMAIN,
        SERVICE_RELOAD,
        reload_service_handler,
        schema=RELOAD_SERVICE_SCHEMA,
    )
    component.async_register_entity_service(
        SERVICE_START,
        {
            vol.Optional(ATTR_DURATION, default=DEFAULT_DURATION):
            cv.time_period
        },
        "async_start",
    )
    component.async_register_entity_service(SERVICE_PAUSE, {}, "async_pause")
    component.async_register_entity_service(SERVICE_CANCEL, {}, "async_cancel")
    component.async_register_entity_service(SERVICE_FINISH, {}, "async_finish")

    return True
Exemplo n.º 55
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the Withings component."""
    conf = config.get(DOMAIN, {})
    if not (conf := config.get(DOMAIN, {})):
        return True
Exemplo n.º 56
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the updater component."""
    conf = config.get(DOMAIN, {})

    for option in (CONF_COMPONENT_REPORTING, CONF_REPORTING):
        if option in conf:
            _LOGGER.warning(
                "Analytics reporting with the option '%s' "
                "is deprecated and you should remove that from your configuration. "
                "The analytics part of this integration has moved to the new 'analytics' integration",
                option,
            )

    async def check_new_version() -> Updater:
        """Check if a new version is available and report if one is."""
        # Skip on dev
        if "dev" in current_version:
            return Updater(False, "", "")

        newest, release_notes = await get_newest_version(hass)

        _LOGGER.debug("Fetched version %s: %s", newest, release_notes)

        # Load data from Supervisor
        if hass.components.hassio.is_hassio():
            core_info = hass.components.hassio.get_core_info()
            newest = core_info["version_latest"]

        # Validate version
        update_available = False
        if AwesomeVersion(newest) > AwesomeVersion(current_version):
            _LOGGER.debug(
                "The latest available version of Home Assistant is %s", newest)
            update_available = True
        elif AwesomeVersion(newest) == AwesomeVersion(current_version):
            _LOGGER.debug(
                "You are on the latest version (%s) of Home Assistant", newest)
        elif AwesomeVersion(newest) < AwesomeVersion(current_version):
            _LOGGER.debug(
                "Local version (%s) is newer than the latest available version (%s)",
                current_version,
                newest,
            )

        _LOGGER.debug("Update available: %s", update_available)

        return Updater(update_available, newest, release_notes)

    coordinator = hass.data[DOMAIN] = update_coordinator.DataUpdateCoordinator[
        Updater](
            hass,
            _LOGGER,
            name="Home Assistant update",
            update_method=check_new_version,
            update_interval=timedelta(days=1),
        )

    # This can take up to 15s which can delay startup
    asyncio.create_task(coordinator.async_refresh())

    hass.async_create_task(
        discovery.async_load_platform(hass, Platform.BINARY_SENSOR, DOMAIN, {},
                                      config))

    return True
Exemplo n.º 57
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the serving of the frontend."""
    await async_setup_frontend_storage(hass)
    hass.components.websocket_api.async_register_command(websocket_get_panels)
    hass.components.websocket_api.async_register_command(websocket_get_themes)
    hass.components.websocket_api.async_register_command(
        websocket_get_translations)
    hass.components.websocket_api.async_register_command(websocket_get_version)
    hass.http.register_view(ManifestJSONView())

    conf = config.get(DOMAIN, {})

    for key in (CONF_EXTRA_HTML_URL, CONF_EXTRA_HTML_URL_ES5, CONF_JS_VERSION):
        if key in conf:
            _LOGGER.error(
                "Please remove %s from your frontend config. It is no longer supported",
                key,
            )

    repo_path = conf.get(CONF_FRONTEND_REPO)
    is_dev = repo_path is not None
    root_path = _frontend_root(repo_path)

    for path, should_cache in (
        ("service_worker.js", False),
        ("robots.txt", False),
        ("onboarding.html", not is_dev),
        ("static", not is_dev),
        ("frontend_latest", not is_dev),
        ("frontend_es5", not is_dev),
    ):
        hass.http.register_static_path(f"/{path}", str(root_path / path),
                                       should_cache)

    hass.http.register_static_path("/auth/authorize",
                                   str(root_path / "authorize.html"), False)
    # https://wicg.github.io/change-password-url/
    hass.http.register_redirect("/.well-known/change-password",
                                "/profile",
                                redirect_exc=web.HTTPFound)

    local = hass.config.path("www")
    if os.path.isdir(local):
        hass.http.register_static_path("/local", local, not is_dev)

    hass.http.app.router.register_resource(IndexView(repo_path, hass))

    async_register_built_in_panel(hass, "profile")

    # To smooth transition to new urls, add redirects to new urls of dev tools
    # Added June 27, 2019. Can be removed in 2021.
    for panel in ("event", "service", "state", "template"):
        hass.http.register_redirect(f"/dev-{panel}",
                                    f"/developer-tools/{panel}")
    for panel in ("logs", "info", "mqtt"):
        # Can be removed in 2021.
        hass.http.register_redirect(f"/dev-{panel}", f"/config/{panel}")
        # Added June 20 2020. Can be removed in 2022.
        hass.http.register_redirect(f"/developer-tools/{panel}",
                                    f"/config/{panel}")

    async_register_built_in_panel(
        hass,
        "developer-tools",
        require_admin=True,
        sidebar_title="developer_tools",
        sidebar_icon="hass:hammer",
    )

    hass.data[DATA_EXTRA_MODULE_URL] = UrlManager(
        conf.get(CONF_EXTRA_MODULE_URL, []))
    hass.data[DATA_EXTRA_JS_URL_ES5] = UrlManager(
        conf.get(CONF_EXTRA_JS_URL_ES5, []))

    await _async_setup_themes(hass, conf.get(CONF_THEMES))

    return True
Exemplo n.º 58
0
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
    """Set up the HomematicIP Cloud component."""
    hass.data[DOMAIN] = {}

    accesspoints = config.get(DOMAIN, [])

    for conf in accesspoints:
        if conf[CONF_ACCESSPOINT] not in configured_haps(hass):
            hass.async_add_job(
                hass.config_entries.flow.async_init(
                    DOMAIN,
                    context={"source": config_entries.SOURCE_IMPORT},
                    data={
                        HMIPC_HAPID: conf[CONF_ACCESSPOINT],
                        HMIPC_AUTHTOKEN: conf[CONF_AUTHTOKEN],
                        HMIPC_NAME: conf[CONF_NAME],
                    },
                ))

    async def _async_activate_eco_mode_with_duration(service):
        """Service to activate eco mode with duration."""
        duration = service.data[ATTR_DURATION]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_absence_with_duration(duration)
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.activate_absence_with_duration(duration)

    hass.services.async_register(
        DOMAIN,
        SERVICE_ACTIVATE_ECO_MODE_WITH_DURATION,
        _async_activate_eco_mode_with_duration,
        schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_DURATION,
    )

    async def _async_activate_eco_mode_with_period(service):
        """Service to activate eco mode with period."""
        endtime = service.data[ATTR_ENDTIME]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_absence_with_period(endtime)
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.activate_absence_with_period(endtime)

    hass.services.async_register(
        DOMAIN,
        SERVICE_ACTIVATE_ECO_MODE_WITH_PERIOD,
        _async_activate_eco_mode_with_period,
        schema=SCHEMA_ACTIVATE_ECO_MODE_WITH_PERIOD,
    )

    async def _async_activate_vacation(service):
        """Service to activate vacation."""
        endtime = service.data[ATTR_ENDTIME]
        temperature = service.data[ATTR_TEMPERATURE]
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.activate_vacation(endtime, temperature)
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.activate_vacation(endtime, temperature)

    hass.services.async_register(
        DOMAIN,
        SERVICE_ACTIVATE_VACATION,
        _async_activate_vacation,
        schema=SCHEMA_ACTIVATE_VACATION,
    )

    async def _async_deactivate_eco_mode(service):
        """Service to deactivate eco mode."""
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.deactivate_absence()
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.deactivate_absence()

    hass.services.async_register(
        DOMAIN,
        SERVICE_DEACTIVATE_ECO_MODE,
        _async_deactivate_eco_mode,
        schema=SCHEMA_DEACTIVATE_ECO_MODE,
    )

    async def _async_deactivate_vacation(service):
        """Service to deactivate vacation."""
        hapid = service.data.get(ATTR_ACCESSPOINT_ID)

        if hapid:
            home = _get_home(hapid)
            if home:
                await home.deactivate_vacation()
        else:
            for hap in hass.data[DOMAIN].values():
                await hap.home.deactivate_vacation()

    hass.services.async_register(
        DOMAIN,
        SERVICE_DEACTIVATE_VACATION,
        _async_deactivate_vacation,
        schema=SCHEMA_DEACTIVATE_VACATION,
    )

    async def _set_active_climate_profile(service):
        """Service to set the active climate profile."""
        entity_id_list = service.data[ATTR_ENTITY_ID]
        climate_profile_index = service.data[ATTR_CLIMATE_PROFILE_INDEX] - 1

        for hap in hass.data[DOMAIN].values():
            if entity_id_list != "all":
                for entity_id in entity_id_list:
                    group = hap.hmip_device_by_entity_id.get(entity_id)
                    if group:
                        await group.set_active_profile(climate_profile_index)
            else:
                for group in hap.home.groups:
                    if isinstance(group, AsyncHeatingGroup):
                        await group.set_active_profile(climate_profile_index)

    hass.services.async_register(
        DOMAIN,
        SERVICE_SET_ACTIVE_CLIMATE_PROFILE,
        _set_active_climate_profile,
        schema=SCHEMA_SET_ACTIVE_CLIMATE_PROFILE,
    )

    async def _async_dump_hap_config(service):
        """Service to dump the configuration of a Homematic IP Access Point."""
        config_path = (service.data.get(ATTR_CONFIG_OUTPUT_PATH)
                       or hass.config.config_dir)
        config_file_prefix = service.data[ATTR_CONFIG_OUTPUT_FILE_PREFIX]
        anonymize = service.data[ATTR_ANONYMIZE]

        for hap in hass.data[DOMAIN].values():
            hap_sgtin = hap.config_entry.title

            if anonymize:
                hap_sgtin = hap_sgtin[-4:]

            file_name = f"{config_file_prefix}_{hap_sgtin}.json"
            path = Path(config_path)
            config_file = path / file_name

            json_state = await hap.home.download_configuration()
            json_state = handle_config(json_state, anonymize)

            config_file.write_text(json_state, encoding="utf8")

    hass.services.async_register(
        DOMAIN,
        SERVICE_DUMP_HAP_CONFIG,
        _async_dump_hap_config,
        schema=SCHEMA_DUMP_HAP_CONFIG,
    )

    def _get_home(hapid: str):
        """Return a HmIP home."""
        hap = hass.data[DOMAIN].get(hapid)
        if hap:
            return hap.home

        _LOGGER.info("No matching access point found for access point id %s",
                     hapid)
        return None

    return True
Exemplo n.º 59
0
def async_setup_platform(hass: HomeAssistantType,
                         config: ConfigType,
                         async_add_devices,
                         discovery_info=None):
    """Set up the cast platform."""
    import pychromecast

    # Import CEC IGNORE attributes
    pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, [])
    hass.data.setdefault(ADDED_CAST_DEVICES_KEY, {})
    hass.data.setdefault(KNOWN_CHROMECASTS_KEY, {})

    # None -> use discovery; (host, port) -> manually specify chromecast.
    want_host = None
    if discovery_info:
        want_host = (discovery_info.get('host'), discovery_info.get('port'))
    elif CONF_HOST in config:
        want_host = (config.get(CONF_HOST), DEFAULT_PORT)

    enable_discovery = False
    if want_host is None:
        # We were explicitly told to enable pychromecast discovery.
        enable_discovery = True
    elif want_host[1] != DEFAULT_PORT:
        # We're trying to add a group, so we have to use pychromecast's
        # discovery to get the correct friendly name.
        enable_discovery = True

    if enable_discovery:

        @callback
        def async_cast_discovered(chromecast):
            """Callback for when a new chromecast is discovered."""
            if want_host is not None and \
                    (chromecast.host, chromecast.port) != want_host:
                return  # for groups, only add requested device
            cast_device = _async_create_cast_device(hass, chromecast)

            if cast_device is not None:
                async_add_devices([cast_device])

        async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED,
                                 async_cast_discovered)
        # Re-play the callback for all past chromecasts, store the objects in
        # a list to avoid concurrent modification resulting in exception.
        for chromecast in list(hass.data[KNOWN_CHROMECASTS_KEY].values()):
            async_cast_discovered(chromecast)

        hass.async_add_job(_setup_internal_discovery, hass)
    else:
        # Manually add a "normal" Chromecast, we can do that without discovery.
        try:
            chromecast = yield from hass.async_add_job(pychromecast.Chromecast,
                                                       *want_host)
        except pychromecast.ChromecastConnectionError:
            _LOGGER.warning("Can't set up chromecast on %s", want_host[0])
            raise
        key = (chromecast.host, chromecast.port, chromecast.uuid)
        cast_device = _async_create_cast_device(hass, chromecast)
        if cast_device is not None:
            hass.data[KNOWN_CHROMECASTS_KEY][key] = chromecast
            async_add_devices([cast_device])
Exemplo n.º 60
0
def _create_weather(knx_module: XKNX, config: ConfigType) -> XknxWeather:
    """Return a KNX weather device to be used within XKNX."""
    return XknxWeather(
        knx_module,
        name=config[CONF_NAME],
        sync_state=config[WeatherSchema.CONF_SYNC_STATE],
        create_sensors=config[WeatherSchema.CONF_KNX_CREATE_SENSORS],
        group_address_temperature=config[
            WeatherSchema.CONF_KNX_TEMPERATURE_ADDRESS],
        group_address_brightness_south=config.get(
            WeatherSchema.CONF_KNX_BRIGHTNESS_SOUTH_ADDRESS),
        group_address_brightness_east=config.get(
            WeatherSchema.CONF_KNX_BRIGHTNESS_EAST_ADDRESS),
        group_address_brightness_west=config.get(
            WeatherSchema.CONF_KNX_BRIGHTNESS_WEST_ADDRESS),
        group_address_brightness_north=config.get(
            WeatherSchema.CONF_KNX_BRIGHTNESS_NORTH_ADDRESS),
        group_address_wind_speed=config.get(
            WeatherSchema.CONF_KNX_WIND_SPEED_ADDRESS),
        group_address_wind_bearing=config.get(
            WeatherSchema.CONF_KNX_WIND_BEARING_ADDRESS),
        group_address_rain_alarm=config.get(
            WeatherSchema.CONF_KNX_RAIN_ALARM_ADDRESS),
        group_address_frost_alarm=config.get(
            WeatherSchema.CONF_KNX_FROST_ALARM_ADDRESS),
        group_address_wind_alarm=config.get(
            WeatherSchema.CONF_KNX_WIND_ALARM_ADDRESS),
        group_address_day_night=config.get(
            WeatherSchema.CONF_KNX_DAY_NIGHT_ADDRESS),
        group_address_air_pressure=config.get(
            WeatherSchema.CONF_KNX_AIR_PRESSURE_ADDRESS),
        group_address_humidity=config.get(
            WeatherSchema.CONF_KNX_HUMIDITY_ADDRESS),
    )