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")
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()
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
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)
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, }, )
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