Example #1
0
 def __init__(self, query_result=[]):
     self._query_result = query_result
     self._receive_queue = aio.Queue()
     self._register_queue = aio.Queue()
     self._async_group = aio.Group()
     self._async_group.spawn(aio.call_on_cancel, self._receive_queue.close)
     self._async_group.spawn(aio.call_on_cancel, self._register_queue.close)
Example #2
0
 def __init__(self, conn: tcp.Connection, always_enabled: bool,
              response_timeout: float, supervisory_timeout: float,
              test_timeout: float, send_window_size: int,
              receive_window_size: int):
     self._conn = conn
     self._always_enabled = always_enabled
     self._is_enabled = always_enabled
     self._response_timeout = response_timeout
     self._supervisory_timeout = supervisory_timeout
     self._test_timeout = test_timeout
     self._send_window_size = send_window_size
     self._receive_window_size = receive_window_size
     self._read_queue = aio.Queue()
     self._write_queue = aio.Queue()
     self._test_event = asyncio.Event()
     self._ssn = 0
     self._rsn = 0
     self._ack = 0
     self._w = 0
     self._write_supervisory_handle = None
     self._waiting_ack_handles = {}
     self._waiting_ack_cv = asyncio.Condition()
     self.async_group.spawn(self._read_loop)
     self.async_group.spawn(self._write_loop)
     self.async_group.spawn(self._test_loop)
     self.async_group.spawn(aio.call_on_cancel, self._on_close)
Example #3
0
async def test_backend_to_frontend(backend, web_server, client, create_msg):
    client_change_queue = aio.Queue()
    client.register_change_cb(lambda: client_change_queue.put_nowait(None))

    entry_queue = aio.Queue()
    backend.register_change_cb(entry_queue.put_nowait)

    await client_change_queue.get()
    assert_client_vs_server_state(client)

    entries = []
    for _ in range(10):
        msg = create_msg()
        await backend.register(ts_now(), msg)
        reg_entries = await entry_queue.get()
        entry = reg_entries[0]
        entries.insert(0, entry)
        await client_change_queue.get()
        assert entry in client.server_state['entries']
        assert util.first(client.server_state['entries'],
                          lambda i: i.msg == msg)
    assert entries == client.server_state['entries']
    assert client.server_state['first_id'] == 1
    assert client.server_state['last_id'] == len(entries)
    assert_client_vs_server_state(client)
Example #4
0
async def test_example_docs():

    from hat import aio
    from hat import juggler
    from hat import util

    port = util.get_unused_tcp_port()
    host = '127.0.0.1'

    server_conns = aio.Queue()
    server = await juggler.listen(host,
                                  port,
                                  server_conns.put_nowait,
                                  autoflush_delay=0)

    client_conn = await juggler.connect(f'ws://{host}:{port}/ws',
                                        autoflush_delay=0)
    server_conn = await server_conns.get()

    server_remote_data = aio.Queue()
    server_conn.register_change_cb(
        lambda: server_remote_data.put_nowait(server_conn.remote_data))

    client_conn.set_local_data(123)
    data = await server_remote_data.get()
    assert data == 123

    await server.async_close()
    await client_conn.wait_closed()
    await server_conn.wait_closed()
Example #5
0
async def test_autoflush_zero(server_port):
    async with create_conn_pair(server_port, 0) as conn_pair:
        conn1, conn2 = conn_pair
        assert conn1.local_data is None
        assert conn1.remote_data is None
        assert conn2.local_data is None
        assert conn2.remote_data is None

        conn1_changes = aio.Queue()
        conn2_changes = aio.Queue()
        conn1.register_change_cb(
            lambda: conn1_changes.put_nowait(conn1.remote_data))
        conn2.register_change_cb(
            lambda: conn2_changes.put_nowait(conn2.remote_data))

        conn1.set_local_data(123)
        conn1.set_local_data('abc')
        conn1.set_local_data('xyz')
        conn2.remote_data is None
        change1 = await conn2_changes.get()
        change2 = await conn2_changes.get()
        change3 = await conn2_changes.get()
        assert change1 == 123
        assert change2 == 'abc'
        assert change3 == 'xyz'
        assert conn2.remote_data == 'xyz'
        assert conn2_changes.empty()
Example #6
0
 def __init__(self, user, roles):
     self._user = user
     self._roles = roles
     self._local_data = None
     self._local_data_queue = aio.Queue()
     self._receive_queue = aio.Queue()
     self._remote_data = None
     self._change_cbs = util.CallbackRegistry()
     self._async_group = aio.Group()
Example #7
0
 def __init__(self):
     self._async_group = aio.Group()
     self._mid_queue = aio.Queue()
     self._global_components_queue = aio.Queue()
     self._local_components_queue = aio.Queue()
     self._mid = 0
     self._local_components = []
     self._global_components = []
     self._change_cbs = util.CallbackRegistry()
Example #8
0
async def test_adapter_remote_data(ui_path, ui_addr, ws_addr,
                                   patch_autoflush_delay):
    conf = {
        'address':
        ui_addr,
        'initial_view':
        None,
        'users': [{
            'name': 'user',
            'password': get_password_conf('pass', 'salt'),
            'roles': [],
            'view': None
        }]
    }
    adapter = Adapter()
    adapters = {'adapter': adapter}
    views = ViewManager({})
    server = await hat.gui.server.create_server(conf, ui_path, adapters, views)
    client = await juggler.connect(ws_addr, autoflush_delay=0)
    await client.send({
        'type': 'login',
        'name': 'user',
        'password': hash_password('pass')
    })
    session = await adapter.session_queue.get()

    assert session.client.remote_data is None
    assert client.remote_data.get('adapter') is None

    frontend_data_queue = aio.Queue()
    session.client.register_change_cb(
        lambda: frontend_data_queue.put_nowait(session.client.remote_data))

    backend_data_queue = aio.Queue()
    client.register_change_cb(
        lambda: backend_data_queue.put_nowait(client.remote_data))

    with pytest.raises(asyncio.TimeoutError):
        await asyncio.wait_for(frontend_data_queue.get(), 0.001)

    with pytest.raises(asyncio.TimeoutError):
        await asyncio.wait_for(backend_data_queue.get(), 0.001)

    client.set_local_data({'adapter': 123})
    data = await frontend_data_queue.get()
    assert data == 123

    session.client.set_local_data('abc')
    data = await backend_data_queue.get()
    assert data == {'adapter': 'abc'}

    await client.async_close()
    await server.async_close()
    await views.async_close()
Example #9
0
async def test_adapter_state(run_gui, gui_conf, tmp_path,
                             event_process, event_client):
    gui_conf = add_adapters_users_roles(gui_conf, tmp_path, no_users_roles=1)
    gui_process = run_gui(gui_conf)

    user_conf = gui_conf['users'][0]
    client = await create_client(gui_conf, user_conf)
    client_change_queue = aio.Queue()
    client.register_change_cb(lambda: client_change_queue.put_nowait(None))
    await client.receive()
    await client.login()
    await client.receive()

    # event server to client
    await register_event(event_client, ('a1', 'data'), {'abc': 1})
    await aio.first(client_change_queue, lambda _: client.server_state)
    assert client.server_state == {'adapter1': [{'abc': 1}]}

    # client to event server
    client.set_local_data({'adapter1': ['a', 'b', 'c']})
    event = await get_first_event(event_client,
                                  lambda e: e.event_type == ('a1', 'action'))
    assert event.payload.data == ['a', 'b', 'c']

    # data with wrong adapter name
    client.set_local_data({'adapter2': ['a', 'b', 'c']})
    event = await get_first_event(event_client,
                                  lambda e: e.event_type == ('a1', 'action'))
    assert event.payload.data is None

    await client.async_close()
    gui_process.close_and_wait_or_kill()
Example #10
0
async def test_frontend_to_backend(backend, web_server, client, create_msg):
    client_change_queue = aio.Queue()
    client.register_change_cb(lambda: client_change_queue.put_nowait(None))
    client.set_filter(common.Filter(msg='message no 1'))

    await client_change_queue.get()
    assert_client_vs_server_state(client)

    for _ in range(10):
        await backend.register(ts_now(), create_msg())
        await client_change_queue.get()

    assert len(client.server_state['entries']) == 2
    assert all('message no 1' in e.msg.msg
               for e in client.server_state['entries'])

    client.set_filter(common.Filter())
    await client_change_queue.get()
    assert len(client.server_state['entries']) == 10
    assert client_change_queue.empty()

    client.set_filter(common.Filter(msg='bla bla'))
    await client_change_queue.get()
    assert len(client.server_state['entries']) == 0
    assert client_change_queue.empty()

    client.set_filter(common.Filter(severity=common.Severity.ERROR))
    await client_change_queue.get()
    assert len(client.server_state['entries']) == 2
    assert all(e.msg.severity == common.Severity.ERROR
               for e in client.server_state['entries'])
Example #11
0
async def test_reconnect(slave_addr, connection_conf):
    slave_queue = aio.Queue()
    server = await modbus.create_tcp_server(modbus.ModbusType.TCP,
                                            slave_addr,
                                            slave_cb=slave_queue.put_nowait)

    conf = {'connection': connection_conf, 'remote_devices': []}

    event_client = EventClient()
    device = await aio.call(master.create, conf, event_client,
                            event_type_prefix)

    slave = await slave_queue.get()
    assert slave.is_open

    assert slave_queue.empty()

    await slave.async_close()

    assert device.is_open

    slave = await slave_queue.get()
    assert slave.is_open

    assert slave_queue.empty()

    await device.async_close()
    await slave.wait_closing()
    await server.async_close()
    await event_client.async_close()
Example #12
0
async def test_read(create_master_slave, modbus_type, comm_type,
                    device_id, data_type, start_address, quantity, result):
    read_queue = aio.Queue()

    async def on_read(slave, device_id, data_type, start_address, quantity):
        f = asyncio.Future()
        entry = device_id, data_type, start_address, quantity, f
        read_queue.put_nowait(entry)
        return await f

    async with create_master_slave(modbus_type, comm_type,
                                   read_cb=on_read) as (master, slave):

        read_future = asyncio.ensure_future(master.read(
            device_id, data_type, start_address, quantity))

        entry = await read_queue.get()
        assert entry[0] == device_id
        assert entry[1] == data_type
        assert entry[2] == start_address
        assert entry[3] == quantity
        entry[4].set_result(result)

        read_result = await read_future
        assert read_result == result
Example #13
0
def _create_connection(
    transport,
    interrogate_cb,
    counter_interrogate_cb,
    command_cb,
):

    info = ConnectionInfo(
        local_addr=Address(*transport.conn.info.local_addr),
        remote_addr=Address(*transport.conn.info.remote_addr))

    conn = Connection()
    conn._transport = transport
    conn._interrogate_cb = interrogate_cb
    conn._counter_interrogate_cb = counter_interrogate_cb
    conn._command_cb = command_cb
    conn._info = info
    conn._interrogate_queue = None
    conn._interrogate_lock = asyncio.Lock()
    conn._counter_interrogate_queue = None
    conn._counter_interrogate_lock = asyncio.Lock()
    conn._data_queue = aio.Queue()
    conn._command_futures = {}
    conn.async_group.spawn(conn._read_loop)
    return conn
Example #14
0
def _create_connection(syntax_names, cosp_conn, cp_ppdu, cpa_ppdu, local_psel,
                       remote_psel):
    cp_user_data = cp_ppdu['normal-mode-parameters']['user-data']
    cpa_user_data = cpa_ppdu['normal-mode-parameters']['user-data']

    conn_req_user_data = (syntax_names.get_name(
        cp_user_data[1][0]['presentation-context-identifier']),
                          cp_user_data[1][0]['presentation-data-values'][1])
    conn_res_user_data = (syntax_names.get_name(
        cpa_user_data[1][0]['presentation-context-identifier']),
                          cpa_user_data[1][0]['presentation-data-values'][1])

    conn = Connection()
    conn._cosp_conn = cosp_conn
    conn._syntax_names = syntax_names
    conn._conn_req_user_data = conn_req_user_data
    conn._conn_res_user_data = conn_res_user_data
    conn._info = ConnectionInfo(local_psel=local_psel,
                                remote_psel=remote_psel,
                                **cosp_conn.info._asdict())
    conn._close_ppdu = _arp_ppdu()
    conn._read_queue = aio.Queue()
    conn._async_group = aio.Group()
    conn._async_group.spawn(conn._read_loop)
    return conn
Example #15
0
async def test_single_state():
    queue = aio.Queue()
    states = [
        stc.State('s1',
                  transitions=[
                      stc.Transition('e1', 's1', ['transit']),
                      stc.Transition('e2', 's1', ['transit'], [], True)
                  ],
                  entries=['enter'],
                  exits=['exit'])
    ]
    actions = {
        'enter': lambda _, e: queue.put_nowait(('enter', e)),
        'exit': lambda _, e: queue.put_nowait(('exit', e)),
        'transit': lambda _, e: queue.put_nowait(('transit', e))
    }
    machine = stc.Statechart(states, actions)
    assert machine.state is None

    f = asyncio.ensure_future(machine.run())
    a, e = await queue.get()
    assert a == 'enter'
    assert e is None
    assert machine.state == 's1'

    await asyncio.sleep(0.001)
    assert queue.empty()

    event = stc.Event('e1', None)
    machine.register(event)
    a, e = await queue.get()
    assert (a, e) == ('exit', event)
    a, e = await queue.get()
    assert (a, e) == ('transit', event)
    a, e = await queue.get()
    assert (a, e) == ('enter', event)
    assert machine.state == 's1'

    await asyncio.sleep(0.001)
    assert queue.empty()

    event = stc.Event('e2', 123)
    machine.register(event)
    a, e = await queue.get()
    assert (a, e) == ('transit', event)
    assert machine.state == 's1'

    await asyncio.sleep(0.001)
    assert queue.empty()

    event = stc.Event('e3', None)
    machine.register(event)
    assert machine.state == 's1'

    await asyncio.sleep(0.001)
    assert queue.empty()

    f.cancel()
    with pytest.raises(asyncio.CancelledError):
        await f
Example #16
0
async def test_query(comm_address, comm_conf):
    event_types = [(), ('a', ), ('b', ), ('a', 'a'), ('a', 'b'),
                   ('a', 'b', 'c'), ('', '', '')]
    events = [
        hat.event.common.Event(event_id=hat.event.common.EventId(server=0,
                                                                 instance=i),
                               event_type=event_type,
                               timestamp=common.now(),
                               source_timestamp=None,
                               payload=None)
        for i, event_type in enumerate(event_types)
    ]
    query_data = common.QueryData()

    query_queue = aio.Queue()

    def query_cb(data):
        query_queue.put_nowait(data)
        return events

    engine = ModuleEngine(query_cb=query_cb)
    comm = await hat.event.server.communication.create(comm_conf, engine)
    client = await hat.event.client.connect(comm_address)

    result = await client.query(query_data)
    assert result == events

    temp_query_data = await query_queue.get()
    assert temp_query_data == query_data

    await client.async_close()
    await comm.async_close()
    await engine.async_close()
Example #17
0
    async def _client_loop(self):
        changes = aio.Queue()

        def on_change():
            remote_data = (self._conn.remote_data if isinstance(
                self._conn.remote_data, dict) else {})
            changes.put_nowait(remote_data.get(self._name))

        try:
            with self._conn.register_change_cb(on_change):
                on_change()

                while True:
                    remote_data = await changes.get()
                    if json.equals(remote_data, self._remote_data):
                        continue

                    self._remote_data = remote_data
                    self._change_cbs.notify()

        except Exception as e:
            mlog.error("client loop error: %s", e, exc_info=e)

        finally:
            self.close()
            self._receive_queue.close()
Example #18
0
async def test_example_docs():

    from hat import aio
    from hat import chatter
    from hat import sbs
    from hat import util

    sbs_repo = sbs.Repository(
        chatter.sbs_repo, r"""
        module Example

        Msg = Integer
    """)

    port = util.get_unused_tcp_port()
    address = f'tcp+sbs://127.0.0.1:{port}'

    server_conns = aio.Queue()
    server = await chatter.listen(sbs_repo, address, server_conns.put_nowait)

    client_conn = await chatter.connect(sbs_repo, address)
    server_conn = await server_conns.get()

    data = chatter.Data('Example', 'Msg', 123)
    client_conn.send(data)

    msg = await server_conn.receive()
    assert msg.data == data

    await server.async_close()
    await client_conn.wait_closed()
    await server_conn.wait_closed()
Example #19
0
async def test_queue_put():
    queue = aio.Queue(1)
    await queue.put(1)
    put_future = asyncio.ensure_future(queue.put(1))
    asyncio.get_event_loop().call_soon(queue.close)
    with pytest.raises(aio.QueueClosedError):
        await put_future
Example #20
0
def test_queue_get_nowait_until_empty():
    queue = aio.Queue()
    queue.put_nowait(1)
    queue.put_nowait(2)
    queue.put_nowait(3)
    result = queue.get_nowait_until_empty()
    assert result == 3
Example #21
0
async def test_event_to_adapters(run_gui, gui_conf, tmp_path,
                                 event_process, event_client):
    no_adapters = 10
    gui_conf = add_adapters_users_roles(gui_conf, tmp_path, no_users_roles=1,
                                        adapters_per_role=no_adapters)
    adapters = [i['name'] for i in gui_conf['adapters']]
    gui_process = run_gui(gui_conf)

    user_conf = gui_conf['users'][0]
    client = await create_client(gui_conf, user_conf)
    client_change_queue = aio.Queue()
    client.register_change_cb(lambda: client_change_queue.put_nowait(None))
    await client.receive()
    await client.login()
    await client.receive()
    await register_event(event_client, ('a1', 'data'), {'abc': 1})

    for adapter in adapters:
        assert await client.receive() == {'type': 'adapter',
                                          'name': adapter,
                                          'data': {'abc': 1}}
    await aio.first(client_change_queue,
                    lambda _: len(client.server_state) == no_adapters)
    assert client.server_state == {a: [{'abc': 1}] for a in adapters}

    await client.async_close()
    gui_process.close_and_wait_or_kill()
Example #22
0
async def test_write(create_master_slave, modbus_type, comm_type,
                     device_id, data_type, start_address, values, result):
    write_queue = aio.Queue()

    async def on_write(slave, device_id, data_type, start_address, values):
        f = asyncio.Future()
        entry = device_id, data_type, start_address, values, f
        write_queue.put_nowait(entry)
        return await f

    async with create_master_slave(modbus_type, comm_type,
                                   write_cb=on_write) as (master, slave):

        write_future = asyncio.ensure_future(master.write(
            device_id, data_type, start_address, values))

        entry = await write_queue.get()
        assert entry[0] == device_id
        assert entry[1] == data_type
        assert entry[2] == start_address
        assert entry[3] == values
        entry[4].set_result(result)

        read_result = await write_future
        assert read_result == result
Example #23
0
async def test_bind_connections(addr, bind_connections, conn_count):
    conn_queue = aio.Queue()
    srv = await tcp.listen(conn_queue.put_nowait,
                           addr,
                           bind_connections=bind_connections)

    conns = []
    for _ in range(conn_count):
        conn1 = await tcp.connect(addr)
        conn2 = await conn_queue.get()

        conns.append((conn1, conn2))

    for conn1, conn2 in conns:
        assert conn1.is_open
        assert conn2.is_open

    await srv.async_close()

    for conn1, conn2 in conns:
        if bind_connections:
            with pytest.raises(ConnectionError):
                await conn1.read()
            assert not conn1.is_open
            assert not conn2.is_open

        else:
            assert conn1.is_open
            assert conn2.is_open

        await conn1.async_close()
        await conn2.async_close()
Example #24
0
    async def create_master_slave(modbus_type, comm_type, read_cb=None,
                                  write_cb=None, write_mask_cb=None):
        if comm_type == CommType.TCP:
            slave_queue = aio.Queue()
            srv = await modbus.create_tcp_server(
                modbus_type, tcp_addr, slave_queue.put_nowait,
                read_cb, write_cb, write_mask_cb)
            master = await modbus.create_tcp_master(
                modbus_type, tcp_addr)
            slave = await slave_queue.get()
            try:
                yield master, slave
            finally:
                await master.async_close()
                await srv.async_close()

        elif comm_type == CommType.SERIAL:
            master = await modbus.create_serial_master(
                modbus_type, nullmodem[0])
            slave = await modbus.create_serial_slave(
                modbus_type, nullmodem[1], read_cb, write_cb, write_mask_cb)
            try:
                yield master, slave
            finally:
                await master.async_close()
                await slave.async_close()

        else:
            raise ValueError()
Example #25
0
async def create(local_addr: typing.Optional[Address] = None,
                 remote_addr: typing.Optional[Address] = None,
                 queue_size: int = 0,
                 **kwargs) -> 'Endpoint':
    """Create new UDP endpoint

    Args:
        local_addr: local address
        remote_addr: remote address
        queue_size: receive queue max size
        kwargs: additional arguments passed to
            :meth:`asyncio.AbstractEventLoop.create_datagram_endpoint`

    """
    endpoint = Endpoint()
    endpoint._local_addr = local_addr
    endpoint._remote_addr = remote_addr
    endpoint._async_group = aio.Group()
    endpoint._queue = aio.Queue(queue_size)

    class Protocol(asyncio.DatagramProtocol):
        def connection_lost(self, exc):
            endpoint._async_group.close()

        def datagram_received(self, data, addr):
            endpoint._queue.put_nowait((data, Address(addr[0], addr[1])))

    loop = asyncio.get_running_loop()
    endpoint._transport, endpoint._protocol = \
        await loop.create_datagram_endpoint(Protocol, local_addr, remote_addr,
                                            **kwargs)
    endpoint._async_group.spawn(aio.call_on_cancel, endpoint._transport.close)
    endpoint._async_group.spawn(aio.call_on_cancel, endpoint._queue.close)
    return endpoint
Example #26
0
async def test_readexactly(addr):
    conn_queue = aio.Queue()
    srv = await tcp.listen(conn_queue.put_nowait, addr)
    conn1 = await tcp.connect(addr)
    conn2 = await conn_queue.get()

    data = b'123'

    result = await conn1.readexactly(0)
    assert result == b''

    conn1.write(data)
    result = await conn2.readexactly(len(data))
    assert result == data

    conn2.write(data)
    result = await conn1.readexactly(len(data) - 1)
    assert result == data[:-1]
    result = await conn1.readexactly(1)
    assert result == data[-1:]

    conn2.write(data)
    await conn2.async_close()
    with pytest.raises(ConnectionError):
        await conn1.readexactly(len(data) + 1)
    with pytest.raises(ConnectionError):
        await conn1.readexactly(1)

    await conn1.async_close()
    await srv.async_close()
Example #27
0
async def create_server(address):
    server = Server()
    server._conn_queue = aio.Queue()
    server._srv = await chatter.listen(
        common.sbs_repo, address,
        lambda conn: server._conn_queue.put_nowait(Connection(conn)))
    return server
Example #28
0
async def test_send_command(addr, command, success):
    conn_queue = aio.Queue()

    async def on_command(conn, commands):
        nonlocal command
        if (isinstance(command.value, iec104.NormalizedValue)
                or isinstance(command.value, iec104.FloatingValue)):
            assert math.isclose(command.value.value,
                                commands[0].value.value,
                                rel_tol=1e-3)
            command = command._replace(value=command.value._replace(
                value=commands[0].value.value))
        assert commands == [command]
        return success

    srv = await iec104.listen(conn_queue.put_nowait,
                              addr,
                              command_cb=on_command)
    conn = await iec104.connect(addr)
    srv_conn = await conn_queue.get()

    result = await conn.send_command(command)
    assert result == success

    await srv.async_close()
    await conn.async_close()
    await srv_conn.async_close()
Example #29
0
async def create_backend(path: Path,
                         low_size: int,
                         high_size: int,
                         enable_archive: bool,
                         disable_journal: bool
                         ) -> 'Backend':
    """Create backend"""
    db = await database.create_database(path, disable_journal)
    try:
        first_id = await db.get_first_id()
        last_id = await db.get_last_id()
    except BaseException:
        await aio.uncancellable(db.async_close())
        raise

    backend = Backend()
    backend._path = path
    backend._low_size = low_size
    backend._high_size = high_size
    backend._enable_archive = enable_archive
    backend._disable_journal = disable_journal
    backend._db = db
    backend._first_id = first_id
    backend._last_id = last_id
    backend._async_group = aio.Group()
    backend._change_cbs = util.CallbackRegistry()
    backend._msg_queue = aio.Queue(register_queue_size)
    backend._executor = aio.create_executor()

    backend._async_group.spawn(aio.call_on_cancel, db.async_close)
    backend._async_group.spawn(backend._loop)

    mlog.debug('created backend with database %s', path)
    return backend
Example #30
0
 def __init__(self, event_client: common.DeviceEventClient,
              event_type_prefix: common.EventTypePrefix):
     self._event_client = event_client
     self._event_type_prefix = event_type_prefix
     self._async_group = event_client.async_group.create_subgroup()
     self._read_queue = aio.Queue()
     self.async_group.spawn(self._read_loop)