Esempio n. 1
0
def setup(hass, config) -> bool:
    """Set up the Rachio component."""
    from rachiopy import Rachio

    # Listen for incoming webhook connections
    hass.http.register_view(RachioWebhookView())

    # Configure API
    api_key = config[DOMAIN].get(CONF_API_KEY)
    rachio = Rachio(api_key)

    # Get the URL of this server
    custom_url = config[DOMAIN].get(CONF_CUSTOM_URL)
    hass_url = hass.config.api.base_url if custom_url is None else custom_url
    rachio.webhook_auth = generate_secret()
    rachio.webhook_url = hass_url + WEBHOOK_PATH

    # Get the API user
    try:
        person = RachioPerson(hass, rachio)
    except AssertionError as error:
        _LOGGER.error("Could not reach the Rachio API: %s", error)
        return False

    # Check for Rachio controller devices
    if not person.controllers:
        _LOGGER.error("No Rachio devices found in account %s", person.username)
        return False
    _LOGGER.info("%d Rachio device(s) found", len(person.controllers))

    # Enable component
    hass.data[DOMAIN] = person
    return True
Esempio n. 2
0
def setup(hass, config) -> bool:
    """Set up the Rachio component."""
    from rachiopy import Rachio

    # Listen for incoming webhook connections
    hass.http.register_view(RachioWebhookView())

    # Configure API
    api_key = config[DOMAIN].get(CONF_API_KEY)
    rachio = Rachio(api_key)

    # Get the URL of this server
    custom_url = config[DOMAIN].get(CONF_CUSTOM_URL)
    hass_url = hass.config.api.base_url if custom_url is None else custom_url
    rachio.webhook_auth = generate_secret()
    rachio.webhook_url = hass_url + WEBHOOK_PATH

    # Get the API user
    try:
        person = RachioPerson(hass, rachio)
    except AssertionError as error:
        _LOGGER.error("Could not reach the Rachio API: %s", error)
        return False

    # Check for Rachio controller devices
    if not person.controllers:
        _LOGGER.error("No Rachio devices found in account %s",
                      person.username)
        return False
    else:
        _LOGGER.info("%d Rachio device(s) found", len(person.controllers))

    # Enable component
    hass.data[DOMAIN] = person
    return True
Esempio n. 3
0
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Set up the Rachio config entry."""

    config = entry.data
    options = entry.options

    # CONF_MANUAL_RUN_MINS can only come from a yaml import
    if not options.get(CONF_MANUAL_RUN_MINS) and config.get(CONF_MANUAL_RUN_MINS):
        options_copy = options.copy()
        options_copy[CONF_MANUAL_RUN_MINS] = config[CONF_MANUAL_RUN_MINS]
        hass.config_entries.async_update_entry(entry, options=options_copy)

    # Configure API
    api_key = config[CONF_API_KEY]
    rachio = Rachio(api_key)

    # Get the URL of this server
    rachio.webhook_auth = secrets.token_hex()
    try:
        webhook_url = await async_get_or_create_registered_webhook_id_and_url(
            hass, entry
        )
    except cloud.CloudNotConnected as exc:
        # User has an active cloud subscription, but the connection to the cloud is down
        raise ConfigEntryNotReady from exc
    rachio.webhook_url = webhook_url

    person = RachioPerson(rachio, entry)

    # Get the API user
    try:
        await person.async_setup(hass)
    except ConfigEntryAuthFailed as error:
        # Reauth is not yet implemented
        _LOGGER.error("Authentication failed: %s", error)
        return False
    except ConnectTimeout as error:
        _LOGGER.error("Could not reach the Rachio API: %s", error)
        raise ConfigEntryNotReady from error

    # Check for Rachio controller devices
    if not person.controllers:
        _LOGGER.error("No Rachio devices found in account %s", person.username)
        return False
    _LOGGER.info(
        "%d Rachio device(s) found; The url %s must be accessible from the internet in order to receive updates",
        len(person.controllers),
        webhook_url,
    )

    # Enable platform
    hass.data.setdefault(DOMAIN, {})[entry.entry_id] = person
    async_register_webhook(hass, entry)

    hass.config_entries.async_setup_platforms(entry, PLATFORMS)

    return True
Esempio n. 4
0
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
    """Set up the Rachio config entry."""

    config = entry.data
    options = entry.options

    # CONF_MANUAL_RUN_MINS can only come from a yaml import
    if not options.get(CONF_MANUAL_RUN_MINS) and config.get(
            CONF_MANUAL_RUN_MINS):
        options_copy = options.copy()
        options_copy[CONF_MANUAL_RUN_MINS] = config[CONF_MANUAL_RUN_MINS]
        hass.config_entries.async_update_entry(entry, options=options_copy)

    # Configure API
    api_key = config[CONF_API_KEY]
    rachio = Rachio(api_key)

    # Get the URL of this server
    custom_url = config.get(CONF_CUSTOM_URL)
    hass_url = hass.config.api.base_url if custom_url is None else custom_url
    rachio.webhook_auth = secrets.token_hex()
    webhook_url_path = f"{WEBHOOK_PATH}-{entry.entry_id}"
    rachio.webhook_url = f"{hass_url}{webhook_url_path}"

    person = RachioPerson(rachio, entry)

    # Get the API user
    try:
        await hass.async_add_executor_job(person.setup, hass)
    # Yes we really do get all these exceptions (hopefully rachiopy switches to requests)
    # and there is not a reasonable timeout here so it can block for a long time
    except RACHIO_API_EXCEPTIONS as error:
        _LOGGER.error("Could not reach the Rachio API: %s", error)
        raise ConfigEntryNotReady

    # Check for Rachio controller devices
    if not person.controllers:
        _LOGGER.error("No Rachio devices found in account %s", person.username)
        return False
    _LOGGER.info("%d Rachio device(s) found", len(person.controllers))

    # Enable component
    hass.data[DOMAIN][entry.entry_id] = person

    # Listen for incoming webhook connections after the data is there
    hass.http.register_view(RachioWebhookView(entry.entry_id,
                                              webhook_url_path))

    for component in SUPPORTED_DOMAINS:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(entry, component))

    return True
Esempio n. 5
0
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
    """Set up the Rachio config entry."""

    config = entry.data
    options = entry.options

    # CONF_MANUAL_RUN_MINS can only come from a yaml import
    if not options.get(CONF_MANUAL_RUN_MINS) and config.get(
            CONF_MANUAL_RUN_MINS):
        options_copy = options.copy()
        options_copy[CONF_MANUAL_RUN_MINS] = config[CONF_MANUAL_RUN_MINS]
        hass.config_entries.async_update_entry(entry, options=options_copy)

    # Configure API
    api_key = config[CONF_API_KEY]
    rachio = Rachio(api_key)

    # Get the URL of this server
    rachio.webhook_auth = secrets.token_hex()
    webhook_id, webhook_url = await async_get_or_create_registered_webhook_id_and_url(
        hass, entry)
    rachio.webhook_url = webhook_url

    person = RachioPerson(rachio, entry)

    # Get the API user
    try:
        await hass.async_add_executor_job(person.setup, hass)
    # Yes we really do get all these exceptions (hopefully rachiopy switches to requests)
    # and there is not a reasonable timeout here so it can block for a long time
    except RACHIO_API_EXCEPTIONS as error:
        _LOGGER.error("Could not reach the Rachio API: %s", error)
        raise ConfigEntryNotReady

    # Check for Rachio controller devices
    if not person.controllers:
        _LOGGER.error("No Rachio devices found in account %s", person.username)
        return False
    _LOGGER.info(
        "%d Rachio device(s) found; The url %s must be accessible from the internet in order to receive updates",
        len(person.controllers),
        webhook_url,
    )

    # Enable component
    hass.data[DOMAIN][entry.entry_id] = person
    async_register_webhook(hass, webhook_id, entry.entry_id)

    for component in SUPPORTED_DOMAINS:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(entry, component))

    return True
Esempio n. 6
0
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
    """Set up the Rachio config entry."""

    config = entry.data
    options = entry.options

    # CONF_MANUAL_RUN_MINS can only come from a yaml import
    if not options.get(CONF_MANUAL_RUN_MINS) and config.get(
            CONF_MANUAL_RUN_MINS):
        options_copy = options.copy()
        options_copy[CONF_MANUAL_RUN_MINS] = config[CONF_MANUAL_RUN_MINS]
        hass.config_entries.async_update_entry(entry, options=options_copy)

    # Configure API
    api_key = config[CONF_API_KEY]
    rachio = Rachio(api_key)

    # Get the URL of this server
    rachio.webhook_auth = secrets.token_hex()
    webhook_id, webhook_url = await async_get_or_create_registered_webhook_id_and_url(
        hass, entry)
    rachio.webhook_url = webhook_url

    person = RachioPerson(rachio, entry)

    # Get the API user
    try:
        await hass.async_add_executor_job(person.setup, hass)
    except ConnectTimeout as error:
        _LOGGER.error("Could not reach the Rachio API: %s", error)
        raise ConfigEntryNotReady from error

    # Check for Rachio controller devices
    if not person.controllers:
        _LOGGER.error("No Rachio devices found in account %s", person.username)
        return False
    _LOGGER.info(
        "%d Rachio device(s) found; The url %s must be accessible from the internet in order to receive updates",
        len(person.controllers),
        webhook_url,
    )

    # Enable platform
    hass.data[DOMAIN][entry.entry_id] = person
    async_register_webhook(hass, webhook_id, entry.entry_id)

    for platform in PLATFORMS:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(entry, platform))

    return True
Esempio n. 7
0
async def validate_input(hass: core.HomeAssistant, data):
    """Validate the user input allows us to connect.

    Data has the keys from DATA_SCHEMA with values provided by the user.
    """
    rachio = Rachio(data[CONF_API_KEY])
    username = None
    try:
        data = await hass.async_add_executor_job(rachio.person.info)
        _LOGGER.debug("rachio.person.getInfo: %s", data)
        if int(data[0][KEY_STATUS]) != HTTPStatus.OK:
            raise InvalidAuth

        rachio_id = data[1][KEY_ID]
        data = await hass.async_add_executor_job(rachio.person.get, rachio_id)
        _LOGGER.debug("rachio.person.get: %s", data)
        if int(data[0][KEY_STATUS]) != HTTPStatus.OK:
            raise CannotConnect

        username = data[1][KEY_USERNAME]
    except ConnectTimeout as error:
        _LOGGER.error("Could not reach the Rachio API: %s", error)
        raise CannotConnect from error

    # Return info that you want to store in the config entry.
    return {"title": username}
Esempio n. 8
0
async def validate_input(hass: core.HomeAssistant, data):
    """Validate the user input allows us to connect.

    Data has the keys from DATA_SCHEMA with values provided by the user.
    """
    rachio = Rachio(data[CONF_API_KEY])
    username = None
    try:
        data = await hass.async_add_executor_job(rachio.person.getInfo)
        _LOGGER.debug("rachio.person.getInfo: %s", data)
        if int(data[0][KEY_STATUS]) != 200:
            raise InvalidAuth

        rachio_id = data[1][KEY_ID]
        data = await hass.async_add_executor_job(rachio.person.get, rachio_id)
        _LOGGER.debug("rachio.person.get: %s", data)
        if int(data[0][KEY_STATUS]) != 200:
            raise CannotConnect

        username = data[1][KEY_USERNAME]
    # Yes we really do get all these exceptions (hopefully rachiopy switches to requests)
    except RACHIO_API_EXCEPTIONS as error:
        _LOGGER.error("Could not reach the Rachio API: %s", error)
        raise CannotConnect

    # Return info that you want to store in the config entry.
    return {"title": username}
Esempio n. 9
0
    def test_validate_authtoken(self):
        rachio = Rachio(authtoken)

        self.assertEqual(
            rachio._headers, {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer %s' % authtoken
            })
Esempio n. 10
0
 def discover(self,api_key=None, **kwargs):
     manifest = self.parent.config.get('manifest', {})
     if api_key is not None: RachioControl.api_key = api_key
     try:
         RachioControl.r_api = Rachio(RachioControl.api_key)
         _person_id = RachioControl.r_api.person.getInfo()
         RachioControl.person_id = _person_id[1]['id']
         self.person = RachioControl.r_api.person.get(RachioControl.person_id) #returns json containing all info associated with person (devices, zones, schedules, flex schedules, and notifications)
     except Exception, ex:
         self.logger.error('Connection Error on RachioControl discovery, may be temporary. %s', str(ex))
         return False
Esempio n. 11
0
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the component."""
    # Get options
    manual_run_mins = config.get(CONF_MANUAL_RUN_MINS)
    _LOGGER.debug("Rachio run time is %d min", manual_run_mins)

    # Get access token
    _LOGGER.debug("Getting Rachio access token...")
    access_token = config.get(CONF_ACCESS_TOKEN)

    # Configure API
    _LOGGER.debug("Configuring Rachio API...")
    from rachiopy import Rachio
    rachio = Rachio(access_token)
    person = None
    try:
        person = _get_person(rachio)
    except KeyError:
        _LOGGER.error("Could not reach the Rachio API. "
                      "Is your access token valid?")
        return False

    # Get and persist devices
    devices = _list_devices(rachio, manual_run_mins)
    if len(devices) == 0:
        _LOGGER.error("No Rachio devices found in account " +
                      person['username'])
        return False
    else:
        hass.data[DATA_RACHIO] = devices[0]

        if len(devices) > 1:
            _LOGGER.warning("Multiple Rachio devices found in account, "
                            "using " + hass.data[DATA_RACHIO].device_id)
        else:
            _LOGGER.info("Found Rachio device")

    hass.data[DATA_RACHIO].update()
    add_devices(hass.data[DATA_RACHIO].list_zones())
    return True