Esempio n. 1
0
    def test_ffmpeg_valid(self):
        """Resolved ffmpeg path should be set if ffmpeg binary detected"""

        logi = self.logi

        # Patch subprocess so that it always returns nothing (implicit success)
        with patch('subprocess.check_call'):
            # Default value should be used if ffmpeg unset.
            self.assertEqual(logi._get_ffmpeg_path(), DEFAULT_FFMPEG_BIN)

            # Input ffmpeg_bin should be respected if valid
            self.assertEqual(logi._get_ffmpeg_path('groovy_ffmpeg'), 'groovy_ffmpeg')

            # Test property on class.
            logi_default_ffmpeg = LogiCircle(client_id="bud",
                                             client_secret="wei",
                                             api_key="serrrrr",
                                             redirect_uri="https://www.youtube.com/watch?v=dQw4w9WgXcQ")
            self.assertEqual(logi_default_ffmpeg.ffmpeg_path, DEFAULT_FFMPEG_BIN)
            logi_custom_ffmpeg = LogiCircle(client_id="bud",
                                            client_secret="wei",
                                            api_key="serrrrr",
                                            redirect_uri="https://www.youtube.com/watch?v=dQw4w9WgXcQ",
                                            ffmpeg_path="super_cool_ffmpeg")
            self.assertEqual(logi_custom_ffmpeg.ffmpeg_path, "super_cool_ffmpeg")
Esempio n. 2
0
    def setUp(self):
        """Setup unit test, create event loop."""
        from logi_circle import LogiCircle

        self.logi = LogiCircle(client_id=CLIENT_ID,
                               client_secret=CLIENT_SECRET,
                               redirect_uri=REDIRECT_URI,
                               cache_file=CACHE_FILE,
                               api_key=API_KEY)
        self.fixtures = FIXTURES
        self.client_id = CLIENT_ID
        self.client_secret = CLIENT_SECRET
        self.redirect_uri = REDIRECT_URI
        self.cache_file = CACHE_FILE

        self.loop = asyncio.new_event_loop()
Esempio n. 3
0
    def _get_authorization_url(self):
        """Create temporary Circle session and generate authorization url."""
        from logi_circle import LogiCircle
        flow = self.hass.data[DATA_FLOW_IMPL][self.flow_impl]
        client_id = flow[CONF_CLIENT_ID]
        client_secret = flow[CONF_CLIENT_SECRET]
        api_key = flow[CONF_API_KEY]
        redirect_uri = flow[CONF_REDIRECT_URI]

        logi_session = LogiCircle(client_id=client_id,
                                  client_secret=client_secret,
                                  api_key=api_key,
                                  redirect_uri=redirect_uri)

        self.hass.http.register_view(LogiCircleAuthCallbackView())

        return logi_session.authorize_url
Esempio n. 4
0
    def test_ffmpeg_invalid(self):
        """Resolved ffmpeg path should None if ffmpeg missing"""

        logi = self.logi

        # Test function
        ffmpeg_path = logi._get_ffmpeg_path('this-is-not-ffmpeg')
        self.assertIsNone(ffmpeg_path)

        # Test property on class.
        logi_bad_ffmpeg = LogiCircle(client_id="bud",
                                     client_secret="wei",
                                     api_key="serrrrr",
                                     redirect_uri="https://www.youtube.com/watch?v=dQw4w9WgXcQ",
                                     ffmpeg_path="this-still-is-not-ffmpeg")

        self.assertIsNone(logi_bad_ffmpeg.ffmpeg_path)
Esempio n. 5
0
    async def _async_create_session(self, code):
        """Create Logi Circle session and entries."""
        from logi_circle import LogiCircle
        from logi_circle.exception import AuthorizationFailed

        flow = self.hass.data[DATA_FLOW_IMPL][DOMAIN]
        client_id = flow[CONF_CLIENT_ID]
        client_secret = flow[CONF_CLIENT_SECRET]
        api_key = flow[CONF_API_KEY]
        redirect_uri = flow[CONF_REDIRECT_URI]
        sensors = flow[CONF_SENSORS]

        logi_session = LogiCircle(
            client_id=client_id,
            client_secret=client_secret,
            api_key=api_key,
            redirect_uri=redirect_uri,
            cache_file=self.hass.config.path(DEFAULT_CACHEDB),
        )

        try:
            with async_timeout.timeout(_TIMEOUT):
                await logi_session.authorize(code)
        except AuthorizationFailed:
            (self.hass.data[DATA_FLOW_IMPL][DOMAIN][EXTERNAL_ERRORS]
             ) = "auth_error"
            return self.async_abort(reason="external_error")
        except asyncio.TimeoutError:
            (self.hass.data[DATA_FLOW_IMPL][DOMAIN][EXTERNAL_ERRORS]
             ) = "auth_timeout"
            return self.async_abort(reason="external_error")

        account_id = (await logi_session.account)["accountId"]
        await logi_session.close()
        return self.async_create_entry(
            title="Logi Circle ({})".format(account_id),
            data={
                CONF_CLIENT_ID: client_id,
                CONF_CLIENT_SECRET: client_secret,
                CONF_API_KEY: api_key,
                CONF_REDIRECT_URI: redirect_uri,
                CONF_SENSORS: sensors,
            },
        )
Esempio n. 6
0
async def async_setup_entry(hass, entry):
    """Set up Logi Circle from a config entry."""

    logi_circle = LogiCircle(
        client_id=entry.data[CONF_CLIENT_ID],
        client_secret=entry.data[CONF_CLIENT_SECRET],
        api_key=entry.data[CONF_API_KEY],
        redirect_uri=entry.data[CONF_REDIRECT_URI],
        cache_file=hass.config.path(DEFAULT_CACHEDB),
    )

    if not logi_circle.authorized:
        hass.components.persistent_notification.create(
            (f"Error: The cached access tokens are missing from {DEFAULT_CACHEDB}.<br />"
             f"Please unload then re-add the Logi Circle integration to resolve."
             ),
            title=NOTIFICATION_TITLE,
            notification_id=NOTIFICATION_ID,
        )
        return False

    try:
        with async_timeout.timeout(_TIMEOUT):
            # Ensure the cameras property returns the same Camera objects for
            # all devices. Performs implicit login and session validation.
            await logi_circle.synchronize_cameras()
    except AuthorizationFailed:
        hass.components.persistent_notification.create(
            "Error: Failed to obtain an access token from the cached "
            "refresh token.<br />"
            "Token may have expired or been revoked.<br />"
            "Please unload then re-add the Logi Circle integration to resolve",
            title=NOTIFICATION_TITLE,
            notification_id=NOTIFICATION_ID,
        )
        return False
    except asyncio.TimeoutError:
        # The TimeoutError exception object returns nothing when casted to a
        # string, so we'll handle it separately.
        err = f"{_TIMEOUT}s timeout exceeded when connecting to Logi Circle API"
        hass.components.persistent_notification.create(
            f"Error: {err}<br />You will need to restart hass after fixing.",
            title=NOTIFICATION_TITLE,
            notification_id=NOTIFICATION_ID,
        )
        return False
    except ClientResponseError as ex:
        hass.components.persistent_notification.create(
            f"Error: {ex}<br />You will need to restart hass after fixing.",
            title=NOTIFICATION_TITLE,
            notification_id=NOTIFICATION_ID,
        )
        return False

    hass.data[DATA_LOGI] = logi_circle

    for component in "camera", "sensor":
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(entry, component))

    async def service_handler(service):
        """Dispatch service calls to target entities."""
        params = dict(service.data)

        if service.service == SERVICE_SET_CONFIG:
            async_dispatcher_send(hass, SIGNAL_LOGI_CIRCLE_RECONFIGURE, params)
        if service.service == SERVICE_LIVESTREAM_SNAPSHOT:
            async_dispatcher_send(hass, SIGNAL_LOGI_CIRCLE_SNAPSHOT, params)
        if service.service == SERVICE_LIVESTREAM_RECORD:
            async_dispatcher_send(hass, SIGNAL_LOGI_CIRCLE_RECORD, params)

    hass.services.async_register(
        DOMAIN,
        SERVICE_SET_CONFIG,
        service_handler,
        schema=LOGI_CIRCLE_SERVICE_SET_CONFIG,
    )

    hass.services.async_register(
        DOMAIN,
        SERVICE_LIVESTREAM_SNAPSHOT,
        service_handler,
        schema=LOGI_CIRCLE_SERVICE_SNAPSHOT,
    )

    hass.services.async_register(
        DOMAIN,
        SERVICE_LIVESTREAM_RECORD,
        service_handler,
        schema=LOGI_CIRCLE_SERVICE_RECORD,
    )

    async def shut_down(event=None):
        """Close Logi Circle aiohttp session."""
        await logi_circle.auth_provider.close()

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, shut_down)

    return True