Beispiel #1
0
    async def get_remote_session_url(self):
        url = self.__queueUrl + '?' + urllib.parse.urlencode(
            {"auth": self.__auth.current_user['idToken']})
        timeout = aiohttp.ClientTimeout(total=6000)
        client_session = aiohttp.ClientSession(timeout=timeout)
        rs_url = None
        rs_post_url = None
        is_offerer = True
        async with sse_client.EventSource(
                url, session=client_session) as event_source:
            try:
                async for event in event_source:
                    print(event)
                    if event.message == 'put' or event.message == 'patch':
                        data = json.loads(event.data)
                        data_path = data['path']
                        data_data = data['data']
                        if data_path == '/':
                            if 'rsUrl' in data_data:
                                rs_url = data_data['rsUrl']
                            if 'rsPostUrl' in data_data:
                                rs_post_url = data_data['rsPostUrl']
                            if 'createAnswer' in data_data:
                                is_offerer = not data_data['createAnswer']
                        elif data_path == '/rsUrl':
                            rs_url = data_data
                    if rs_url != None:
                        break
                print(event)
                self.__taskQueueKeepAlive.cancel()
            except ConnectionError:
                pass

        await client_session.close()
        return rs_url, rs_post_url, is_offerer
Beispiel #2
0
async def _streamSSEAsync(url, exit=None):
    """internal"""
    from asyncio import Event

    from aiohttp_sse_client import client as sse_client
    from aiostream.stream import merge

    async with sse_client.EventSource(url) as event_source:
        if isinstance(exit, Event):

            async def _waitExit():
                yield await exit.wait()

            waits = (_waitExit(), event_source)
        else:
            waits = (event_source,)

        try:
            async with merge(*waits).stream() as stream:
                try:
                    async for event in stream:
                        if event == True:  # noqa: E712
                            return
                        yield json.loads(event.data)
                except ConnectionError:
                    raise PyEXception("Could not connect to SSE Stream")
                except PyEXStopSSE:
                    return
                except BaseException:
                    raise
        except (json.JSONDecodeError, KeyboardInterrupt):
            raise
Beispiel #3
0
    async def __aiter__(self) -> AsyncIterator[events.CommandEventContext]:
        from aiohttp_sse_client import client as sse_client  # type: ignore

        api_client = self._api.api_client
        host = api_client.configuration.host
        headers = api_client.default_headers

        api_client.update_params_for_auth(headers, None, ["app_key"])

        activity_id = self._activity_id
        batch_id = self._batch_id
        last_idx = self._size - 1

        async with sse_client.EventSource(
            f"{host}/activity/{activity_id}/exec/{batch_id}",
            headers=headers,
            timeout=self.seconds_left(),
        ) as event_source:
            try:
                async for msg_event in event_source:
                    try:
                        evt_ctx = _command_event_ctx(msg_event)
                    except Exception as exc:  # noqa
                        _log.error(f"Event stream exception (batch {batch_id}): {exc}")
                    else:
                        yield evt_ctx
                        if evt_ctx.computation_finished(last_idx):
                            break
            except ClientPayloadError as exc:
                _log.error(f"Event payload error (batch {batch_id}): {exc}")
            except ConnectionError:
                raise
            except asyncio.TimeoutError:
                raise BatchTimeoutError()
Beispiel #4
0
async def test_eventsource_reconnect_event():
    """Test EventSource: reconnection event.
    
    ..seealso: https://github.com/web-platform-tests/wpt/blob/master/
    eventsource/eventsource-reconnect.htm
    """
    opened = False
    reconnected = False

    def on_error():
        nonlocal reconnected
        assert source.ready_state == sse_client.READY_STATE_CONNECTING
        assert opened is True
        reconnected = True

    async with sse_client.EventSource(
            WPT_SERVER +
            'resources/status-reconnect.py?status=200&ok_first&id=2',
            reconnection_time=timedelta(milliseconds=2),
            on_error=on_error) as source:
        async for e in source:
            if not opened:
                opened = True
                assert reconnected is False
                assert e.data == "ok"
            else:
                assert reconnected is True
                assert e.data == "data"
                break
async def test_eventsource_request_cancellation():
    """Test EventSource: reconnection event.
    
    ..seealso: https://github.com/web-platform-tests/wpt/blob/master/
    eventsource/eventsource-request-cancellation.htm
    """
    closed = False

    def on_open():
        if closed:
            assert False

    def on_error():
        assert source.ready_state == sse_client.READY_STATE_CLOSED

    try:
        async with sse_client.EventSource(
                WPT_SERVER + 'resources/message.py?sleep=1000&message=' +
                "retry:1000\ndata:abc\n\n",
                on_open=on_open,
                on_error=on_error) as source:
            raise ConnectionAbortedError
    except ConnectionAbortedError:
        closed = True
        await asyncio.sleep(1)
        assert source.ready_state == sse_client.READY_STATE_CLOSED
        pass
    async def connect(self, reconnect_time: Optional[float] = 5):
        """
        Connect to the beefweb eventsource and begin listening for events.

        :param Optional[float] reconnect_time: The number of seconds to wait
            between reconnection attempts.
        """
        if self.is_connected():
            return
        reconnect_time = timedelta(seconds=reconnect_time)

        # necessary to prevent connection from timing out after 5 minutes
        timeout = ClientTimeout(sock_read=0)
        self._session = ClientSession(timeout=timeout)

        self._connection = sse_client.EventSource(
            self._url,
            session=self._session,
            headers=self._headers,
            reconnection_time=reconnect_time,
            max_connect_retry=1000000000,
            on_error=self._connection_error_handler,
        )

        loop = asyncio.get_event_loop()
        self._event_reader = loop.create_task(self._read_events())
Beispiel #7
0
async def test_format_field_id_2():
    """Test EventSource: Last-Event-ID (2).

    ..seealso: https://github.com/web-platform-tests/wpt/blob/master/
    eventsource/format-field-id-2.htm
    """
    counter = 0

    async with sse_client.EventSource(
        WPT_SERVER + 'resources/last-event-id.py',
    ) as source:
        async for e in source:
            if counter == 0:
                counter += 1
                assert e.data == "hello"
                # default last event id is Unicode U+2026
                assert e.last_event_id == "…"
                last_id = e.last_event_id
            elif counter in (1, 2):
                counter += 1
                assert e.data == last_id
                assert e.last_event_id == last_id
                break
            else:
                fail("Unexpected counter {}".format(counter))
async def test_eventsource_close():
    """Test EventSource: close.
    
    ..seealso: https://github.com/web-platform-tests/wpt/blob/master/
    eventsource/eventsource-close.htm
    """
    source = sse_client.EventSource(WPT_SERVER + 'resources/message.py')
    assert source.ready_state == sse_client.READY_STATE_CONNECTING
    await source.connect()
    assert source.ready_state == sse_client.READY_STATE_OPEN
    await source.close()
    assert source.ready_state == sse_client.READY_STATE_CLOSED

    count = 0
    reconnected = False

    def on_error():
        nonlocal count, reconnected
        if count == 1:
            assert source.ready_state == sse_client.READY_STATE_CONNECTING
            reconnected = True
        elif count == 2:
            assert source.ready_state == sse_client.READY_STATE_CONNECTING
            count += 1
        elif count == 3:
            assert source.ready_state == sse_client.READY_STATE_CLOSED
        else:
            assert False

    async with sse_client.EventSource(
            WPT_SERVER + 'resources/reconnect-fail.py?id=' +
            str(datetime.utcnow().timestamp()),
            reconnection_time=timedelta(milliseconds=2),
            on_error=on_error) as source:
        try:
            async for e in source:
                if count == 0:
                    assert reconnected is False
                    assert e.data == "opened"
                elif count == 1:
                    assert reconnected is True
                    assert e.data == "reconnected"
                else:
                    assert False
                count += 1
        except ConnectionError:
            pass
Beispiel #9
0
async def test_request_post_to_connect():
    """Test EventSource option method for connection.
    """
    source = sse_client.EventSource(WPT_SERVER + 'resources/message.py',
                                    option={'method': "POST"})
    await source.connect()
    async for e in source:
        assert e.data == "data"
        break
    await source.close()
async def publish():
    """Read events from pub-sub channel."""
    redis = await aioredis.create_redis_pool(redis_url)
    while True:
        async with sse_client.EventSource(wikimedia_stream) as event_source:
            try:
                async for event in event_source:
                    json.loads(event.data)
                    await redis.publish(pubsub_channel, event.data)
            except (ConnectionError, aio.TimeoutError, aio.CancelledError):
                pass
Beispiel #11
0
        async def _req(url=url, json=json, wrap=wrap, field=field):
            async with sse_client.EventSource(url) as event_source:
                async for event in event_source:
                    data = event.data

                    if json:
                        data = JSON.loads(data)
                    if field:
                        data = data[field]
                    if wrap:
                        data = [data]
                    yield data
Beispiel #12
0
async def get_stream(url_from: str):
    async with sse_client.EventSource(url_from) as event_source:
        try:
            async for event in event_source:
                try:
                    change = json.loads(event.data)
                except ValueError:
                    pass
                else:
                    yield change
        except Exception as error:
            logger.error(f"Error occurred: {error}")
async def test_eventsource_close():
    """Test EventSource: close.
    
    ..seealso: https://github.com/web-platform-tests/wpt/blob/master/
    eventsource/eventsource-close.htm
    """
    source = sse_client.EventSource(WPT_SERVER + 'resources/message.py')
    assert source.ready_state == sse_client.READY_STATE_CONNECTING
    await source.connect()
    assert source.ready_state == sse_client.READY_STATE_OPEN
    await source.close()
    assert source.ready_state == sse_client.READY_STATE_CLOSED
async def get_events():
    conn = aiohttp.TCPConnector()
    auth = aiohttp.BasicAuth(args.user, args.password)
    client = aiohttp.ClientSession(connector=conn, auth=auth)
    async with sse_client.EventSource("http://" + args.controller + ":8181" +
                                      args.uri,
                                      session=client) as event_source:
        try:
            async for event in event_source:
                logger.info(event)
        except ConnectionError:
            pass
async def subscribe_collateral():
    async with sse_client.EventSource(args.url + '/borrower/events',
                                      headers=headers,
                                      timeout=-1) as event_source:
        try:
            async for msg in event_source:
                print(msg)

        except Exception as error:
            err_msg = repr(error)
            print(err_msg)
            pass
Beispiel #16
0
    async def test(status):
        def on_error():
            assert source.ready_state == sse_client.READY_STATE_CLOSED

        def on_message():
            assert source.ready_state == sse_client.READY_STATE_OPEN

        source = sse_client.EventSource(
            WPT_SERVER + 'resources/status-error.py?status=' + str(status),
            on_message=on_message,
            on_error=on_error)
        with pytest.raises(ConnectionError):
            await source.connect()
Beispiel #17
0
async def test_rquest_accept():
    """Test EventSource: Accept header.

    ..seealso: https://github.com/web-platform-tests/wpt/blob/master/
    eventsource/request-accept.htm
    """
    source = sse_client.EventSource(WPT_SERVER +
                                    'resources/accept.event_stream?pipe=sub')
    await source.connect()
    async for e in source:
        assert e.data == "text/event-stream"
        break
    await source.close()
Beispiel #18
0
async def test_eventsource_reconnect():
    """Test EventSource: reconnection.
    
    ..seealso: https://github.com/web-platform-tests/wpt/blob/master/
    eventsource/eventsource-reconnect.htm
    """
    source = sse_client.EventSource(WPT_SERVER +
                                    'resources/status-reconnect.py?status=200')
    await source.connect()
    async for e in source:
        assert e.data == 'data'
        break
    await source.close()
Beispiel #19
0
async def test_rquest_cache_control():
    """Test EventSource: Cache-Control.

    ..seealso: https://github.com/web-platform-tests/wpt/blob/master/
    eventsource/request-cache-control.htm
    """
    source = sse_client.EventSource(
        WPT_SERVER + 'resources/cache-control.event_stream?pipe=sub')
    await source.connect()
    async for e in source:
        assert e.data == "no-cache"
        break
    await source.close()
    async def process_updates(self):
        from aiohttp_sse_client import client as sse_client
        from aiohttp import ClientTimeout

        _LOGGER.debug('Starting sse reader')
        token = await self._auth_session.token()
        headers = {'Accept-Language': 'en-US', 'Authorization': token}
        tries = 0

        while True:
            try:
                async with sse_client.EventSource(
                        _build_api_url('/homeappliances/{haid}/events',
                                       self._haId),
                        session=self._auth_session.session,
                        headers=headers,
                        timeout=ClientTimeout(total=None)) as event_source:
                    self._hass.async_create_task(self.fetch_initial_state())
                    async for event in event_source:
                        tries = 0  # Reset backoff if we read any event successfully
                        if event.type != 'KEEP-ALIVE':
                            _LOGGER.debug('Received event: %s', event)
                        if event.data:
                            try:
                                data = json.loads(event.data)
                                for item in data['items']:
                                    if 'key' in item and 'value' in item:
                                        self.handle_key_value(
                                            item['key'], item['value'])
                            except Exception as e:
                                _LOGGER.debug('SSE reader failed parsing %s',
                                              event.data)
                        elif event.type == 'DISCONNECTED':
                            self.handle_key_value('DISCONNECTED', '')
                            pass
                        elif event.type == 'CONNECTED':
                            self._hass.async_create_task(
                                self.fetch_initial_state())
                            pass
            except ConnectionError as ce:
                _LOGGER.debug('SSE reader caught connection error: %s', ce)
                if '401' in ce.args[0]:  # Ugly way to extract http status
                    _LOGGER.debug('Fetching new access token')
                    token = await self._auth_session.token(
                        headers['Authorization'])
                    headers['Authorization'] = token
                tries += 1
            except Exception as e:
                _LOGGER.debug('SSE reader caught exception: %s', e)
                tries += 1
            await asyncio.sleep(min(600, 2**tries))
Beispiel #21
0
async def stream_events(url='https://api.blaseball.com/events/streamData', retry_base=0.01, retry_max=300, on_parse_error='LOG'):
    """
    Async generator for the events API.
    `retry_base` will be the minimum time to delay if there's a connection error
    `retry_max` is the maximum time to delay if there's a connection error
    """
    retry_delay = retry_base
    event_current = {}
    delta_previous = None
    while True:
        try:
            async with sse_client.EventSource(url, read_bufsize=2 ** 19) as src:
                async for event in src:
                    retry_delay = retry_base  # reset backoff
                    if not event.data:
                        continue
                    raw_event = ujson.loads(event.data)
                    if 'value' in raw_event.keys(): # New, full event
                        delta_previous = None
                        event_current = raw_event['value']
                        payload = event_current
                    elif 'delta' in raw_event.keys(): # Delta event
                        if raw_event['delta'] == delta_previous:
                            continue
                        delta_previous = raw_event['delta']
                        jsonpatch.apply_patch(event_current, raw_event['delta'], in_place=True)
                        payload = event_current
                    else:
                        raise ValueError("Unknown event type: {}".format(raw_event.keys()))
                    yield payload
        except (ConnectionError,
                TimeoutError,
                ClientPayloadError,
                futures.TimeoutError,
                asyncio.exceptions.TimeoutError,
                ClientConnectorError,
                ServerDisconnectedError):
            await asyncio.sleep(retry_delay)
            retry_delay = min(retry_delay * 2, retry_max)
        except (jsonpatch.JsonPatchConflict,
                jsonpointer.JsonPointerException,
                IndexError,
                ValueError) as error:
            if on_parse_error.lower()=='skip':
                pass
            elif on_parse_error.lower()=='raise':
                print("Event parse error.")
                raise
            else: # log and restart, default
                print("Event parse error.")
                print(error)
Beispiel #22
0
async def start_sse_event_listener():
    try:
        # cache so we don't have to look up every event
        _load_json = load_json
        _see_handler = on_sse_event

        event_prefix = 'openhab' if not IS_OH2 else 'smarthome'

        async with sse_client.EventSource(
                url=f'{HTTP_PREFIX}/rest/events?topics='
                f'{event_prefix}/items/,'  # Item updates
                f'{event_prefix}/channels/,'  # Channel update
                f'{event_prefix}/things/*/status,'  # Thing status updates
                f'{event_prefix}/things/*/statuschanged'  # Thing status changes
                ,
                session=HTTP_SESSION) as event_source:
            async for event in event_source:

                e_str = event.data

                try:
                    e_json = _load_json(e_str)
                except ValueError:
                    log_events.warning(f'Invalid json: {e_str}')
                    continue
                except TypeError:
                    log_events.warning(f'Invalid json: {e_str}')
                    continue

                # Log sse event
                if log_events.isEnabledFor(logging.DEBUG):
                    log_events._log(logging.DEBUG, e_str, [])

                # process
                _see_handler(e_json)

    except asyncio.CancelledError:
        # This exception gets raised if we cancel the coroutine
        # since this is normal behaviour we ignore this exception
        pass
    except Exception as e:
        disconnect = is_disconnect_exception(e)
        lvl = logging.WARNING if disconnect else logging.ERROR
        log.log(lvl, f'SSE request Error: {e}')
        for line in traceback.format_exc().splitlines():
            log.log(lvl, line)

        # reconnect even if we have an unexpected error
        if not disconnect:
            set_offline(f'Uncaught error in process_sse_events: {e}')
Beispiel #23
0
async def start_sse_event_listener():
    try:
        # cache so we don't have to look up every event
        call = ON_SSE_EVENT

        options = {}
        if HABApp.CONFIG.openhab.connection.user or HABApp.CONFIG.openhab.connection.password:
            options['with_credentials'] = True

        event_prefix = 'openhab' if not IS_OH2 else 'smarthome'

        async with sse_client.EventSource(
                url=f'{HTTP_PREFIX}/rest/events?topics='
                f'{event_prefix}/items/,'  # Item updates
                f'{event_prefix}/channels/,'  # Channel update
                f'{event_prefix}/things/*/status,'  # Thing status updates
                f'{event_prefix}/things/*/statuschanged'  # Thing status changes
                ,
                option=options,
                session=HTTP_SESSION) as event_source:
            async for event in event_source:
                try:
                    event = load_json(event.data)
                except ValueError:
                    continue
                except TypeError:
                    continue

                # Log sse event
                if log_events.isEnabledFor(logging.DEBUG):
                    log_events._log(logging.DEBUG, event, [])

                # process
                call(event)

    except asyncio.CancelledError:
        # This exception gets raised if we cancel the coroutine
        # since this is normal behaviour we ignore this exception
        pass
    except Exception as e:
        disconnect = is_disconnect_exception(e)
        lvl = logging.WARNING if disconnect else logging.ERROR
        log.log(lvl, f'SSE request Error: {e}')
        for line in traceback.format_exc().splitlines():
            log.log(lvl, line)

        # reconnect even if we have an unexpected error
        if not disconnect:
            set_offline(f'Uncaught error in process_sse_events: {e}')
Beispiel #24
0
    async def test(status):
        def on_error():
            assert False

        def on_open():
            assert source.ready_state == sse_client.READY_STATE_OPEN

        source = sse_client.EventSource(WPT_SERVER.replace(
            'eventsource', 'common/redirect.py?'
            'location=/eventsource/resources/message.py&status=' +
            str(status)),
                                        on_open=on_open,
                                        on_error=on_error)
        await source.connect()
        await source.close()
Beispiel #25
0
    async def connect(self):
        """Connect to Nest Stream API."""
        if self._session is None:
            self._session = aiohttp.ClientSession()
        if self._session.closed:
            raise ConnectionRefusedError('session is closed')

        if (self._access_token_expires_at is not None
                and self._access_token_expires_at < datetime.utcnow()):
            raise ConnectionRefusedError('access token is expired')

        self._event_stream = sse_client.EventSource(
            API_URL + '/',
            headers={'Authorization': 'Bearer {}'.format(self._access_token)},
            session=self._session)
        await self._event_stream.connect()
async def test_eventsource_onopen():
    """Test EventSource: open (announcing the connection).
    
    ..seealso: https://github.com/web-platform-tests/wpt/blob/master/
    eventsource/eventsource-onopen.htm
    """
    def on_open():
        """Callback for open event."""
        assert source.ready_state == sse_client.READY_STATE_OPEN
    
    source = sse_client.EventSource(WPT_SERVER + 'resources/message.py',
                                    on_open=on_open)
    assert source.ready_state == sse_client.READY_STATE_CONNECTING
    await source.connect()
    assert source.ready_state == sse_client.READY_STATE_OPEN
    await source.close()
Beispiel #27
0
        async def startJukeboxConnection(self):

            try:
                newdevice = {"jukebox": {"name": "Jukebox", "nowplaying": {}}}
                await self.dataset.ingest({"player": newdevice})
                while self.running == True:
                    try:
                        self.log.info('.. starting jukebox SSE connection')
                        # This should establish an SSE connection with the Jukebox
                        timeout = aiohttp.ClientTimeout(total=0)
                        async with sse_client.EventSource(
                                self.config.jukebox_url + "/sse",
                                timeout=timeout) as event_source:
                            try:
                                async for event in event_source:
                                    #self.log.info('.. SSE: %s' % event)
                                    try:
                                        data = json.loads(event.data)
                                        if 'nowplaying' in data:
                                            self.log.info('<< %s' % data)
                                            await self.dataset.ingest({
                                                "player": {
                                                    "jukebox": {
                                                        "nowplaying":
                                                        data['nowplaying']
                                                    }
                                                }
                                            })
                                    except:
                                        self.log.error('error parsing data',
                                                       exc_info=True)
                            except ConnectionError:
                                self.log.error('!! error with SSE connection',
                                               exc_info=True)
                        self.log.warning('!! SSE connection ended?')
                    except aiohttp.client_exceptions.ClientConnectorCertificateError:
                        self.log.error(
                            '!! error - jukebox SSL certificate error')
                    except concurrent.futures._base.TimeoutError:
                        self.log.error('!! error - jukebox SSE timeout')
                    except:
                        self.log.error(
                            '!! error starting jukebox SSE connection',
                            exc_info=True)
            except:
                self.log.error('!! Error in Jukebox connection loop',
                               exc_info=True)
Beispiel #28
0
async def test_eventsource_onmessage():
    """Test EventSource: onmessage.
    
    ..seealso: https://github.com/web-platform-tests/wpt/blob/master/
    eventsource/eventsource-onmessage.htm
    """
    def on_message(event):
        """Callback for message event."""
        assert event.data == "data"
    
    source = sse_client.EventSource(WPT_SERVER + 'resources/message.py',
                                    on_message=on_message)
    await source.connect()
    async for e in source:
        assert e.data == "data"
        break
    await source.close()
Beispiel #29
0
async def _streamSSEAsync(url, accrue=False):
    """internal"""
    from aiohttp_sse_client import client as sse_client

    async with sse_client.EventSource(url) as event_source:
        try:
            async for event in event_source:
                yield json.loads(event.data)

        except (json.JSONDecodeError, KeyboardInterrupt):
            raise
        except ConnectionError:
            raise PyEXception("Could not connect to SSE Stream")
        except PyEXStopSSE:
            return
        except Exception:
            raise
    return
Beispiel #30
0
    async def connect(self):
        self.__received_messages = {}  # empty dict for received messages
        headers = {
            "Authorization": "Bearer " + self.__auth.current_user['idToken'],
            'content-type': 'application/json'
        }
        self._http = aiohttp.ClientSession(headers=headers)

        path = self.__rs_url + '?' + urllib.parse.urlencode(
            {"auth": self.__auth.current_user['idToken']})
        timeout = aiohttp.ClientTimeout(total=6000)
        self._session = aiohttp.ClientSession(timeout=timeout)
        self.__event_source = sse_client.EventSource(
            path,
            session=self._session,
            on_message=self.rs_message,
            on_error=self.rs_error)
        await self.__event_source.connect()
        self.__rs_task = asyncio.ensure_future(self.rs_listen())