8000 Client · timkpaine/csp-gateway Wiki · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
github-actions[bot] edited this page Mar 25, 2025 · 1 revision

Gateway Client Example

Here is a notebook demonstrating the fundamentals of the GatewayClient object.

This class is a convenience wrapper around the various HTTP requests used to interact with a running GatewayServer (with REST endpoints enabled). It relies on the httpx and aiohttp libraries, and derives most of its functionality from the openapi specification provided on the running GatewayServer (usually available at /openapi.json).

Client Configuration

A GatewayClient is configured via a GatewayClientConfig, a minimal pydantic model to specify details such as protocol (http/https), host, port, etc. By default, we should provide host and port.

We can also specify in the config return_raw_json, which specifies whether we would like to return the raw json response, or a ResponseWrapper object for REST requests. The ResponseWrapper object can provide both the raw json message, as well as a pandas dataframe. The ResponseWrapper contains additional type information which will create column names and utilize the correct data type for the constructed pandas dataframe.

Client Methods

A client as a small number of general-purpose methods. In alphabetical order:

  • controls: managment controls for monitoring/configurating the running server
  • last: get the last ticked data value on a channel
  • lookup: lookup a piece of data by id
  • next: get the next ticked data value on a channel
  • send: send some data onto a channel
  • state: get the value of a given channel's state accumulator

Additionally, a client has some streaming methods available when websockets are configured:

  • stream: call a callback when a channel ticks
  • subscribe: subscribe to data on a channel
  • unsubscribe: unsubscribe to data on a channel

Let's explore some of the functionality of the basic demo server. To start, we should run the demo server in another process (with the omnibus config):

csp-gateway-start --config-dir=csp_gateway/server/demo +config=omnibus

By default, this will run the server on localhost:8000.

Imports

All the important objects are hoisted to the top level csp_gateway. Lets import and setup our client.

from csp_gateway import GatewayClient, GatewayClientConfig
config = GatewayClientConfig(host="localhost", port=8000, return_raw_json=False)
client = GatewayClient(config)

The first time we use our client, it will take a little longer than usual as it tries to interrogate the running server's openapi specification for available methods. Once done, our request will go through, and subsequent requests will leverage this specification. Let's start with some simple status checks. If we're curious about available endpoints, we can navigate to http://localhost:8000/redoc (or generally http://<hostname>:<port>/redoc if we're running on a different host)

# heartbeat check
client.controls("heartbeat").as_json()
[{'id': '7180742829515',
  'timestamp': '2025-03-14T06:00:12.399921',
  'name': 'heartbeat',
  'status': 'ok',
  'data': {},
  'data_str': ''}]
# openapi spec
from IPython.display import JSON
JSON(client._openapi_spec)
<IPython.core.display.JSON object>
# machine stats
client.controls("stats").as_json()
[{'id': '7180742829516',
  'timestamp': '2025-03-14T06:00:12.562785',
  'name': 'stats',
  'status': 'ok',
  'data': {'cpu': 0.0,
   'memory': 63.7,
   'memory-total': 36.28,
   'pid': 1750281,
   'active_threads': 4,
   'max_threads': 'unlimited',
   'now': '2025-03-14T06:00:12.564110',
   'csp-now': '2025-03-14T06:00:12.563004',
   'host': 'devqtccrt06',
   'user': 'nk12433'},
  'data_str': '{"cpu":0.0,"memory":63.7,"memory-total":36.28,"pid":1750281,"active_threads":4,"max_threads":"unlimited","now":"2025-03-14T06:00:12.564110","csp-now":"2025-03-14T06:00:12.563004","host":"devqtccrt06","user":"nk12433"}'}]

Last, State, Lookup, Send

Let's look at what channels we have available for last:

client.last().as_json()
['controls', 'basket', 'never_ticks', 'example', 'example_list', 'str_basket']
client.last("example").as_json()
[{'id': '7182204802295',
  'timestamp': '2025-03-14T06:00:12.274734',
  'x': 31,
  'y': '303030',
  'internal_csp_struct': {'z': 12},
  'data': [],
  'mapping': {},
  'dt': '2025-03-14T01:59:42.200557',
  'd': '2025-03-14'}]
client.last("basket").as_json()
[{'id': '7182204802295',
  'timestamp': '2025-03-14T06:00:12.274734',
  'x': 31,
  'y': '303030',
  'internal_csp_struct': {'z': 12},
  'data': [],
  'mapping': {},
  'dt': '2025-03-14T01:59:42.200557',
  'd': '2025-03-14'},
 {'id': '7182204802292',
  'timestamp': '2025-03-14T06:00:12.269265',
  'x': 30,
  'y': '3030',
  'internal_csp_struct': {'z': 12},
  'data': [0.918037522903988,
   0.3399226261577962,
   0.7909028689829906,
   0.7039079146913827,
   0.8210556057950636,
   0.07325613777603324,
   0.36257073731882594,
   0.3946540193539001,
   0.5774311632755368,
   0.20316200054623546],
  'mapping': {'30': 30},
  'dt': '2025-03-14T01:59:42.200557',
  'd': '2025-03-14'},
 {'id': '7182204802293',
  'timestamp': '2025-03-14T06:00:12.274455',
  'x': 30,
  'y': '303030',
  'internal_csp_struct': {'z': 12},
  'data': [0.4562437422860882,
   0.9004249706550138,
   0.6477939153762935,
   0.3803206666410205,
   0.775542818358652,
   0.021906915016978834,
   0.8893453580688346,
   0.8277048024826046,
   0.46538738841821836,
   0.456588879024889],
  'mapping': {'30': 30},
  'dt': '2025-03-14T01:59:42.200557',
  'd': '2025-03-14'}]
client.last("basket").as_pandas_df()
id timestamp x y data dt d internal_csp_struct.z mapping.30 mapping
0 7182204802295 2025-03-14T06:00:12.274734 31 303030 [] 2025-03-14T01:59:42.200557 2025-03-14 12 NaN NaN
1 7182204802292 2025-03-14T06:00:12.269265 30 3030 [0.918037522903988, 0.3399226261577962, 0.7909... 2025-03-14T01:59:42.200557 2025-03-14 12 30.0 NaN
2 7182204802293 2025-03-14T06:00:12.274455 30 303030 [0.4562437422860882, 0.9004249706550138, 0.647... 2025-03-14T01:59:42.200557 2025-03-14 12 30.0 NaN

State channels are used to perform state accumulation over a number of ticks. The example server doesn't do anything too interesting, but we can access these channels nevertheless.

client.state().as_json()
['example']
client.state("example").as_pandas_df().tail()

# We note that there are a large number of columns in the above dataframe.
# This is because `mapping` is a dict with different keys for eery row.
# To accomodate all of them, the returned pandas dataframe has a column for any key present in the `mapping` attribute of any `ExampleData` Struct
id timestamp x y data dt d internal_csp_struct.z mapping.1 mapping.2 ... mapping.22 mapping.23 mapping.24 mapping.25 mapping.26 mapping.27 mapping.28 mapping.29 mapping.30 mapping
40 7182204802285 2025-03-14T06:00:10.264122 28 282828 [0.5303914536525036, 0.0010628925807091294, 0.... 2025-03-14T01:59:42.200557 2025-03-14 12 NaN NaN ... NaN NaN NaN NaN NaN NaN 28.0 NaN NaN NaN
41 7182204802286 2025-03-14T06:00:10.264259 29 282828 [] 2025-03-14T01:59:42.200557 2025-03-14 12 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
42 7182204802290 2025-03-14T06:00:11.264179 29 292929 [0.7784380063762434, 0.7909368694127872, 0.647... 2025-03-14T01:59:42.200557 2025-03-14 12 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN 29.0 NaN NaN
43 7182204802294 2025-03-14T06:00:12.274565 30 303030 [0.847968392664959, 0.34935942519328944, 0.265... 2025-03-14T01:59:42.200557 2025-03-14 12 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 30.0 NaN
44 7182204802295 2025-03-14T06:00:12.274734 31 303030 [] 2025-03-14T01:59:42.200557 2025-03-14 12 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

5 rows × 39 columns

We can lookup individual data points using lookup. This is a bit of a silly example when we're just looking at a single channel, but can be valuable when you have lots of interconnected channels.

# get the last tick, then lookup by id
last = client.last("example").as_json()[0]
last_id = last["id"]
client.lookup("example", last_id).as_json()
[{'id': '7182204802295',
  'timestamp': '2025-03-14T06:00:12.274734',
  'x': 31,
  'y': '303030',
  'internal_csp_struct': {'z': 12},
  'data': [],
  'mapping': {},
  'dt': '2025-03-14T01:59:42.200557',
  'd': '2025-03-14'}]

Finally, we can send our own data into the API using send.

client.send(
    "example",
    {
        "x": 12,
        "y": "HEY!",
        "internal_csp_struct": {"z": 13}
    }
)

client.state("example").as_pandas_df().tail()
id timestamp x y data dt d internal_csp_struct.z mapping.1 mapping.2 ... mapping.22 mapping.23 mapping.24 mapping.25 mapping.26 mapping.27 mapping.28 mapping.29 mapping.30 mapping
42 7182204802290 2025-03-14T06:00:11.264179 29 292929 [0.7784380063762434, 0.7909368694127872, 0.647... 2025-03-14T01:59:42.200557 2025-03-14 12 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN 29.0 NaN NaN
43 7182204802294 2025-03-14T06:00:12.274565 30 303030 [0.847968392664959, 0.34935942519328944, 0.265... 2025-03-14T01:59:42.200557 2025-03-14 12 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN 30.0 NaN
44 7182204802295 2025-03-14T06:00:12.274734 31 303030 [] 2025-03-14T01:59:42.200557 2025-03-14 12 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
45 7182204802296 2025-03-14T06:00:13.034311 12 HEY! [] 2025-03-14T01:59:42.200557 2025-03-14 13 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
46 7182204802297 2025-03-14T06:00:13.035209 13 HEY! [] 2025-03-14T01:59:42.200557 2025-03-14 12 NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

5 rows × 39 columns

The REST API uses pydantic validation for send requests. Since ExampleData has a __validators__ attribute defined, the pydantic version of the GatewayStruct has those functions ran for validation before propagating the sent value through the graph. ExampleData has validation performed that asserts the value of x is not negative. When we try to pass a negative value in, we get an error on the send, but the graph does not crash. The details of the error are provided in the response.

client.send("example", {"x": -12, "y": "HEY!"})
ServerUnprocessableException: [{'type': 'list_type', 'loc': ['body', 'list[function-wrap[create_instance()]]'], 'msg': 'Input should be a valid list', 'input': {'x': -12, 'y': 'HEY!'}}, {'type': 'value_error', 'loc': ['body', 'function-wrap[create_instance()]', 'x'], 'msg': 'Value error, value must be non-negative.', 'input': -12, 'ctx': {'error': {}}}]

Next

The running GatewayServer is a synchronous system, and we're interacting it via asynchronous REST requests. However, we can still perform actions like "wait for the next tick". This can be dangerous and lead to race conditions, but it can still be useful in certain circumstances.

client.next("example").as_json()
[{'id': '7182204802346',
  'timestamp': '2025-03-14T06:00:23.264154',
  'x': 41,
  'y': '414141',
  'internal_csp_struct': {'z': 12},
  'data': [0.8434439910392343,
   0.16425120769202894,
   0.4614001200974842,
   0.5296539732016515,
   0.7793370635405895,
   0.8968921920130971,
   0.16515287895221997,
   0.9002092496268692,
   0.15540237095341358,
   0.5879171201018687],
  'mapping': {'41': 41},
  'dt': '2025-03-14T01:59:42.200557',
  'd': '2025-03-14'}]

Note that this call will block until the next value ticks.

Streaming

If our webserver is configured with websockets, we can also stream data out of channels. A simple example that prints out channel data is provided.

client.stream(channels=["example"], callback=print)
{'channel': 'example', 'data': [{'id': '7182204802364', 'timestamp': '2025-03-14T06:00:27.264171', 'x': 45, 'y': '454545', 'internal_csp_struct': {'z': 12}, 'data': [0.6512409372233339, 0.07206425449741505, 0.5459898400764014, 0.9069291031159893, 0.5632205038815109, 0.6358680416497396, 0.4031860150585428, 0.18951576663682146, 0.13029048524663422, 0.6537721971743142], 'mapping': {'45': 45}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802368', 'timestamp': '2025-03-14T06:00:28.264253', 'x': 46, 'y': '464646', 'internal_csp_struct': {'z': 12}, 'data': [0.13347377162286045, 0.14766463082192083, 0.890098581009976, 0.5762928909003212, 0.9784598838743355, 0.9093206966012796, 0.4421107198172203, 0.6351323300210804, 0.8580132723903817, 0.8155427123499257], 'mapping': {'46': 46}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802369', 'timestamp': '2025-03-14T06:00:28.264459', 'x': 47, 'y': '464646', 'internal_csp_struct': {'z': 12}, 'data': [], 'mapping': {}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802373', 'timestamp': '2025-03-14T06:00:29.264267', 'x': 47, 'y': '474747', 'internal_csp_struct': {'z': 12}, 'data': [0.9770241512799153, 0.9637667972653557, 0.9594704907592322, 0.13620074749494915, 0.02682378617576875, 0.21212555291360513, 0.22007092181222787, 0.38504292634018655, 0.9342337231196015, 0.4290203133079068], 'mapping': {'47': 47}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802377', 'timestamp': '2025-03-14T06:00:30.264338', 'x': 48, 'y': '484848', 'internal_csp_struct': {'z': 12}, 'data': [0.892430583670491, 0.12591388868359998, 0.9224444538829644, 0.0029365846224427283, 0.8455103482206909, 0.6064336013949906, 0.7146470440362958, 0.7172194103168975, 0.5344556625030702, 0.12551306544964813], 'mapping': {'48': 48}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802378', 'timestamp': '2025-03-14T06:00:30.264578', 'x': 49, 'y': '484848', 'internal_csp_struct': {'z': 12}, 'data': [], 'mapping': {}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802382', 'timestamp': '2025-03-14T06:00:31.264269', 'x': 49, 'y': '494949', 'internal_csp_struct': {'z': 12}, 'data': [0.7954525130520012, 0.16105077513514243, 0.6697700523760823, 0.18214767845076874, 0.031965065384497615, 0.3704517634058897, 0.8063898928948885, 0.9372302738066902, 0.12448951223205629, 0.3723664774669405], 'mapping': {'49': 49}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}



KeyboardInterrupt

Asynchronous client

All of the above can also be used in an async fashion. Note that by default, the GatewayClient class is an alias for the SyncGatewayClient class. The only differences are:

  • all methods are async instead of synchronous
  • stream is an infinite generator, rather than callback-based (so takes no callback argument)
from csp_gateway import AsyncGatewayClient
async_client= AsyncGatewayClient(config)
# We can subscribe to multiple channels, including dict-baskets
async def print_all():
    async for datum in async_client.stream(channels=["example", "example_list", ("basket", "A")]):
        print(datum)
await print_all()
{'channel': 'example_list', 'data': [{'id': '7182204802436', 'timestamp': '2025-03-14T06:00:43.264033', 'x': 61, 'y': '616161', 'internal_csp_struct': {'z': 12}, 'data': [0.2012890963221904, 0.702376333618334, 0.361342696585941, 0.7383356341385855, 0.5439924770669536, 0.5348101969493174, 0.7261873522256002, 0.8653648126326041, 0.22990047589634643, 0.6788906270823372], 'mapping': {'61': 61}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802436', 'timestamp': '2025-03-14T06:00:43.264033', 'x': 61, 'y': '616161', 'internal_csp_struct': {'z': 12}, 'data': [0.2012890963221904, 0.702376333618334, 0.361342696585941, 0.7383356341385855, 0.5439924770669536, 0.5348101969493174, 0.7261873522256002, 0.8653648126326041, 0.22990047589634643, 0.6788906270823372], 'mapping': {'61': 61}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'basket', 'key': 'A', 'data': [{'id': '7182204802433', 'timestamp': '2025-03-14T06:00:43.263949', 'x': 61, 'y': '61', 'internal_csp_struct': {'z': 12}, 'data': [0.37515205241819904, 0.21653802732210348, 0.6023670041905677, 0.7020115328362944, 0.5672014845851433, 0.3315506604647509, 0.2835119310422646, 0.17365652828157507, 0.7197090506662692, 0.32070439406165585], 'mapping': {'61': 61}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example_list', 'data': [{'id': '7182204802440', 'timestamp': '2025-03-14T06:00:44.264059', 'x': 62, 'y': '626262', 'internal_csp_struct': {'z': 12}, 'data': [0.46296344196914896, 0.535262117154687, 0.8713255531129767, 0.15089077117115202, 0.9314969920967638, 0.49322856675566407, 0.5097354278193875, 0.36542150764786463, 0.0978733899463935, 0.6526308371221453], 'mapping': {'62': 62}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802440', 'timestamp': '2025-03-14T06:00:44.264059', 'x': 62, 'y': '626262', 'internal_csp_struct': {'z': 12}, 'data': [0.46296344196914896, 0.535262117154687, 0.8713255531129767, 0.15089077117115202, 0.9314969920967638, 0.49322856675566407, 0.5097354278193875, 0.36542150764786463, 0.0978733899463935, 0.6526308371221453], 'mapping': {'62': 62}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'basket', 'key': 'A', 'data': [{'id': '7182204802437', 'timestamp': '2025-03-14T06:00:44.263975', 'x': 62, 'y': '62', 'internal_csp_struct': {'z': 12}, 'data': [0.940523191216232, 0.14852620784066317, 0.08189176013369992, 0.9043729968792783, 0.05089580688345152, 0.7942753901732218, 0.25601515448071055, 0.708127323757491, 0.42466967147061263, 0.1237637046040877], 'mapping': {'62': 62}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802441', 'timestamp': '2025-03-14T06:00:44.264377', 'x': 63, 'y': '626262', 'internal_csp_struct': {'z': 12}, 'data': [], 'mapping': {}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'basket', 'key': 'A', 'data': [{'id': '7182204802441', 'timestamp': '2025-03-14T06:00:44.264377', 'x': 63, 'y': '626262', 'internal_csp_struct': {'z': 12}, 'data': [], 'mapping': {}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example_list', 'data': [{'id': '7182204802445', 'timestamp': '2025-03-14T06:00:45.264058', 'x': 63, 'y': '636363', 'internal_csp_struct': {'z': 12}, 'data': [0.31908694135855364, 0.3778381445552632, 0.7861888413413884, 0.9574250161776887, 0.5833248271672732, 0.308015510869482, 0.8170552095029715, 0.3533446051973852, 0.565398159234985, 0.9591750226310537], 'mapping': {'63': 63}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802445', 'timestamp': '2025-03-14T06:00:45.264058', 'x': 63, 'y': '636363', 'internal_csp_struct': {'z': 12}, 'data': [0.31908694135855364, 0.3778381445552632, 0.7861888413413884, 0.9574250161776887, 0.5833248271672732, 0.308015510869482, 0.8170552095029715, 0.3533446051973852, 0.565398159234985, 0.9591750226310537], 'mapping': {'63': 63}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'basket', 'key': 'A', 'data': [{'id': '7182204802442', 'timestamp': '2025-03-14T06:00:45.263969', 'x': 63, 'y': '63', 'internal_csp_struct': {'z': 12}, 'data': [0.26219215598319245, 0.7876415886108106, 0.46734385893262653, 0.5875585649183716, 0.6973450587166122, 0.19938357748148694, 0.5681164164813136, 0.08582575356430155, 0.5822429915710623, 0.032509795763884575], 'mapping': {'63': 63}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example_list', 'data': [{'id': '7182204802449', 'timestamp': '2025-03-14T06:00:46.264050', 'x': 64, 'y': '646464', 'internal_csp_struct': {'z': 12}, 'data': [0.8423317626185829, 0.20973759581109863, 0.5292314592966805, 0.8273340088284135, 0.16798011294997617, 0.3954567336148307, 0.4363356424438266, 0.15038572422882712, 0.30525781171354893, 0.2066455497558468], 'mapping': {'64': 64}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802449', 'timestamp': '2025-03-14T06:00:46.264050', 'x': 64, 'y': '646464', 'internal_csp_struct': {'z': 12}, 'data': [0.8423317626185829, 0.20973759581109863, 0.5292314592966805, 0.8273340088284135, 0.16798011294997617, 0.3954567336148307, 0.4363356424438266, 0.15038572422882712, 0.30525781171354893, 0.2066455497558468], 'mapping': {'64': 64}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'basket', 'key': 'A', 'data': [{'id': '7182204802446', 'timestamp': '2025-03-14T06:00:46.263966', 'x': 64, 'y': '64', 'internal_csp_struct': {'z': 12}, 'data': [0.5186648328191604, 0.20600018613504822, 0.2517255629965035, 0.2027172299603618, 0.6973958971974537, 0.018533961127689347, 0.8831800860672222, 0.15443494355861742, 0.7879460672351232, 0.5737498259238871], 'mapping': {'64': 64}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802450', 'timestamp': '2025-03-14T06:00:46.264341', 'x': 65, 'y': '646464', 'internal_csp_struct': {'z': 12}, 'data': [], 'mapping': {}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'basket', 'key': 'A', 'data': [{'id': '7182204802450', 'timestamp': '2025-03-14T06:00:46.264341', 'x': 65, 'y': '646464', 'internal_csp_struct': {'z': 12}, 'data': [], 'mapping': {}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example_list', 'data': [{'id': '7182204802454', 'timestamp': '2025-03-14T06:00:47.264053', 'x': 65, 'y': '656565', 'internal_csp_struct': {'z': 12}, 'data': [0.38361199716851, 0.4318530809990534, 0.3327373711769688, 0.19177499312477841, 0.8238340463975228, 0.3122577782035033, 0.26085183935102385, 0.12676280253692418, 0.27222241778232015, 0.8142830554492966], 'mapping': {'65': 65}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802454', 'timestamp': '2025-03-14T06:00:47.264053', 'x': 65, 'y': '656565', 'internal_csp_struct': {'z': 12}, 'data': [0.38361199716851, 0.4318530809990534, 0.3327373711769688, 0.19177499312477841, 0.8238340463975228, 0.3122577782035033, 0.26085183935102385, 0.12676280253692418, 0.27222241778232015, 0.8142830554492966], 'mapping': {'65': 65}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'basket', 'key': 'A', 'data': [{'id': '7182204802451', 'timestamp': '2025-03-14T06:00:47.263966', 'x': 65, 'y': '65', 'internal_csp_struct': {'z': 12}, 'data': [0.0892006794893967, 0.07876938817599266, 0.9480755640114016, 0.8956409788136256, 0.1765617680441619, 0.34959327017659225, 0.5691499047953102, 0.6197869710008492, 0.4247627740185159, 0.22229884776814335], 'mapping': {'65': 65}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example_list', 'data': [{'id': '7182204802458', 'timestamp': '2025-03-14T06:00:48.264056', 'x': 66, 'y': '666666', 'internal_csp_struct': {'z': 12}, 'data': [0.785907903315688, 0.20499171133424998, 0.1997585736271853, 0.8400504706317495, 0.5078353527827971, 0.17751926740421575, 0.240514889413168, 0.7795065353794545, 0.10821747119526537, 0.013346638048011616], 'mapping': {'66': 66}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802458', 'timestamp': '2025-03-14T06:00:48.264056', 'x': 66, 'y': '666666', 'internal_csp_struct': {'z': 12}, 'data': [0.785907903315688, 0.20499171133424998, 0.1997585736271853, 0.8400504706317495, 0.5078353527827971, 0.17751926740421575, 0.240514889413168, 0.7795065353794545, 0.10821747119526537, 0.013346638048011616], 'mapping': {'66': 66}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'basket', 'key': 'A', 'data': [{'id': '7182204802455', 'timestamp': '2025-03-14T06:00:48.263975', 'x': 66, 'y': '66', 'internal_csp_struct': {'z': 12}, 'data': [0.9441185853333258, 0.7659205422168367, 0.5186970325300565, 0.7140712043958034, 0.8653320532574393, 0.8233499006198564, 0.5896847424112025, 0.07401817792364396, 0.17173762100190504, 0.864687792136789], 'mapping': {'66': 66}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'example', 'data': [{'id': '7182204802459', 'timestamp': '2025-03-14T06:00:48.264360', 'x': 67, 'y': '666666', 'internal_csp_struct': {'z': 12}, 'data': [], 'mapping': {}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'basket', 'key': 'A', 'data': [{'id': '7182204802459', 'timestamp': '2025-03-14T06:00:48.264360', 'x': 67, 'y': '666666', 'internal_csp_struct': {'z': 12}, 'data': [], 'mapping': {}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}



CancelledError
# We can susbscribe to every tick from a dict basket by just subscribing to the full basket
async def print_all_basket():
    async for datum in async_client.stream(channels=["str_basket"]):
        print(datum)
await print_all_basket()
{'channel': 'str_basket', 'key': 'a', 'data': [{'id': '7182204802482', 'timestamp': '2025-03-14T06:00:54.263974', 'x': 72, 'y': '72', 'internal_csp_struct': {'z': 12}, 'data': [0.0024343396429761244, 0.25557971088785525, 0.8830889612103591, 0.5248708862100656, 0.13301440206288329, 0.0613374033071844, 0.9533501115434322, 0.17519376229750483, 0.20826938545917772, 0.3154244464812893], 'mapping': {'72': 72}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'str_basket', 'key': 'b', 'data': [{'id': '7182204802483', 'timestamp': '2025-03-14T06:00:54.264023', 'x': 72, 'y': '7272', 'internal_csp_struct': {'z': 12}, 'data': [0.8477714975000878, 0.8761447163517748, 0.4132611178713649, 0.035190170106964236, 0.6786254800475836, 0.9475667654798842, 0.5866246994077503, 0.26298570997111104, 0.31639906057837064, 0.3663114982586084], 'mapping': {'72': 72}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'str_basket', 'key': 'c', 'data': [{'id': '7182204802484', 'timestamp': '2025-03-14T06:00:54.264041', 'x': 72, 'y': '727272', 'internal_csp_struct': {'z': 12}, 'data': [0.3332323138368375, 0.05696328615646484, 0.23548236793906674, 0.2820311457311522, 0.9589706357912199, 0.44038637040590844, 0.19630430868230497, 0.7453123881812489, 0.1878259296575574, 0.17223653057513189], 'mapping': {'72': 72}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'str_basket', 'key': 'a', 'data': [{'id': '7182204802487', 'timestamp': '2025-03-14T06:00:55.263971', 'x': 73, 'y': '73', 'internal_csp_struct': {'z': 12}, 'data': [0.6919631440411455, 0.4728617807619395, 0.0003944547125812603, 0.011758757622944871, 0.09775418165142358, 0.9825827730540471, 0.869142195037153, 0.06360846203630244, 0.6391038358448057, 0.18918471862707165], 'mapping': {'73': 73}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'str_basket', 'key': 'b', 'data': [{'id': '7182204802488', 'timestamp': '2025-03-14T06:00:55.264023', 'x': 73, 'y': '7373', 'internal_csp_struct': {'z': 12}, 'data': [0.23318761968678847, 0.7916938531654325, 0.16766945067832806, 0.30717503529152856, 0.7234609518781409, 0.6761783642820521, 0.012291838679474254, 0.3734093437402387, 0.25193367414091183, 0.4116290421307852], 'mapping': {'73': 73}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'str_basket', 'key': 'c', 'data': [{'id': '7182204802489', 'timestamp': '2025-03-14T06:00:55.264041', 'x': 73, 'y': '737373', 'internal_csp_struct': {'z': 12}, 'data': [0.9995663904683157, 0.49037285862321134, 0.9360403966245218, 0.32907171896712595, 0.8706475080400187, 0.9358547470908197, 0.6094950522388487, 0.3187147239906233, 0.5146210935507332, 0.2468259549948888], 'mapping': {'73': 73}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'str_basket', 'key': 'a', 'data': [{'id': '7182204802491', 'timestamp': '2025-03-14T06:00:56.263987', 'x': 74, 'y': '74', 'internal_csp_struct': {'z': 12}, 'data': [0.30780427957177736, 0.31783225533438253, 0.28974485377085746, 0.8056785399315933, 0.6550343960061931, 0.51147587370349, 0.22918318357951206, 0.27483544636782764, 0.1617784534805391, 0.12615374449682082], 'mapping': {'74': 74}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'str_basket', 'key': 'b', 'data': [{'id': '7182204802492', 'timestamp': '2025-03-14T06:00:56.264040', 'x': 74, 'y': '7474', 'internal_csp_struct': {'z': 12}, 'data': [0.7597865185560577, 0.9542811639842493, 0.3548238255188084, 0.5497091911407666, 0.2103980379131476, 0.9282153309075862, 0.019933785131218018, 0.07818556433746526, 0.8906613298984217, 0.4142275174628044], 'mapping': {'74': 74}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'str_basket', 'key': 'c', 'data': [{'id': '7182204802493', 'timestamp': '2025-03-14T06:00:56.264059', 'x': 74, 'y': '747474', 'internal_csp_struct': {'z': 12}, 'data': [0.5351854446981592, 0.7247690029219567, 0.8073854595040114, 0.7157206622262171, 0.4352917223246313, 0.4369240091155152, 0.16633677865466623, 0.39403050678439466, 0.5964420480684727, 0.4549142654097128], 'mapping': {'74': 74}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'str_basket', 'key': 'a', 'data': [{'id': '7182204802496', 'timestamp': '2025-03-14T06:00:57.263968', 'x': 75, 'y': '75', 'internal_csp_struct': {'z': 12}, 'data': [0.5464599879444142, 0.721937878646433, 0.8743734166377515, 0.19869546159445028, 0.13465567320565885, 0.13731281812355312, 0.985981130222794, 0.7543303190330615, 0.17166394918759065, 0.7745127544725419], 'mapping': {'75': 75}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'str_basket', 'key': 'b', 'data': [{'id': '7182204802497', 'timestamp': '2025-03-14T06:00:57.264016', 'x': 75, 'y': '7575', 'internal_csp_struct': {'z': 12}, 'data': [0.014886231617977641, 0.8035620841240536, 0.6303792158456698, 0.3810092650960091, 0.36235076847179437, 0.6273491033528601, 0.04515741170281928, 0.40411733708766073, 0.5610236907135676, 0.8084273295250559], 'mapping': {'75': 75}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}
{'channel': 'str_basket', 'key': 'c', 'data': [{'id': '7182204802498', 'timestamp': '2025-03-14T06:00:57.264034', 'x': 75, 'y': '757575', 'internal_csp_struct': {'z': 12}, 'data': [0.14440123791521808, 0.41124092584685856, 0.558344424856301, 0.7197882892005704, 0.6791006750064388, 0.9625438604579102, 0.9079986744434172, 0.5810653358542905, 0.42340551567499196, 0.6309477160315278], 'mapping': {'75': 75}, 'dt': '2025-03-14T01:59:42.200557', 'd': '2025-03-14'}]}



CancelledError
Clone this wiki locally
0