synapse-runtime-sdk
The Python SDK for the Synapse runtime: publish and subscribe to topics, serve and call services, keep shared values current with the store, and move H.264 video — all from asyncio.
pip install synapse-runtime-sdk # the SDK
pip install "synapse-runtime-sdk[video]" # + the H.264 encoder/decoder (CPU or NVIDIA)
Linux x86_64, Python ≥ 3.11. A Synapse runtime to connect to: curl -fsSL <release host>/install.sh | bash.
The surface in one screen
from pydantic import BaseModel
from synapse_sdk import Synapse, Topic, Service, Api, ServiceError, SynapseError
class Imu(BaseModel):
accel: tuple[float, float, float]
imu = Topic("imu", schema=Imu) # datagram (default): one datagram per message, newest wins
log = Topic("log", delivery="stream") # ordered, nothing dropped
api = Api(arm=dict(get_pose=Service(input=dict, output=dict))) # api.arm.get_pose.name == "arm/get_pose"
async with Synapse("https://localhost:4470/synapse", "agent", "sim-1") as node: # type agent|observer|web|hmi; the name is minted when absent
pub = await node.publisher(imu) # resolves once the runtime admitted it on the current session
pub.publish(Imu(accel=(0, 0, 9.8))) # synchronous; validated by the schema; dropped+counted while unbound
async for batch in node.subscribe(imu): # one read = the newest message of each publisher (queue_depth=0: every message)
for msg in batch:
print(msg.publisher, msg.data.accel, msg.t_us)
view = node.view(imu, stale_time_ms=200); await view.ready(); print(view.get().data)
reg = await node.serve(api.arm.get_pose, lambda inp, ctx: {"frame": inp["frame"]}) # (input, ctx) -> result; sync runs in a thread, async on the loop
pose = await node.call(api.arm.get_pose, {"frame": "tool0"}, deadline_ms=1000) # await the Run for the result
run = node.call("arm/move_to", {"target": 1}); async for u in run.updates(): ...; await run.cancel()
board = await node.store("mission/board", access="public"); await board.set("phase", "loading"); board.value["phase"] # a value kept current
@node.every(hz=50) # a fixed grid while the node lives (polling bridges)
def poll(): pub.publish(read_imu())
- Identity:
Synapse(url, type, name=None, user_id=None, credential=None).typebounds the role the runtime grants (agent→agent;web/hmi→observeruntil promoted on a project); aweb/hminode withoutuser_idmints one.node.info()hasname,prefix,role,robot,broker_version. - Sessions come and go, the node stays: a lost session is replaced (
reconnect=True, backoffreconnect_initial_ms→reconnect_max_ms), every publisher, registration, subscription and namespace replays its intent on the new session; in-flight calls failconnection_lost; nothing is resumed.node.status/async for s in node.watch_status()/node.on_status(cb).reconnect=Falseends the nodeclosedon a drop. - The runtime decides:
publisher(),serve(),store()resolve on admission; a refusal (already_registered,unauthorized,owner_taken, ...) is asked again, paced, with a warning each time (warn=callback, defaultlogging). - Time:
t_usis the publisher's clock, microseconds.node.clock(),node.time_offsets(),node.to_local_us(t_us, dom),node.age_us(msg);deadline_ms=on a subscription drops a message older than that in our own time domain. - Errors: one
SynapseError(code, message, data, retryable);ServiceError(code, message, data)raised by a handler crosses verbatim (data.appfor an application code); the same error codes in every language. - Media:
Topic(name, content_type="video/h264", fec=True, layout={...})(raw bytes in FEC symbols);VideoPublisher.open(node, topic, encoder),VideoSubscriber(node, topic, decoder, on_image=); see below. - The certificate pin (
broker_cert_sha256=) is discovered when absent (SYNAPSE_BROKER_CERT_SHA256, thenhttp://host:port/certificate.sha256). SIGINT/SIGTERM close every open node, then re-raise (signals=Falseopts out). - Timeouts and periods are
_msintegers everywhere, in every language.
Examples
Getting started, one verb per file: examples/getting-started/python/01_connect.py … 11_store.py in the repository.
Video in five lines
from synapse_sdk import Synapse, now_us
from synapse_sdk.media import H264Encoder, H264Decoder, VideoPublisher, VideoSubscriber
enc = H264Encoder(640, 360, 30, bitrate_kbps=2000, backend="auto") # nvenc when a GPU is there, else x264
vp = await VideoPublisher.open(node, "cam/h264", enc) # video/h264 datagram topic with fec + layout; serves `cam/h264/idr`
vp.push(i420_uint8_array, now_us()) # (h*3/2, w) numpy, or (y, u, v) planes; no copy
vs = VideoSubscriber(node, "cam/h264", H264Decoder(), on_image=lambda img: np.asarray(img.y)) # zero-copy planes
Metadata
Release files for synapse-runtime-sdk 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| synapse_runtime_sdk-0.2.1-cp311-abi3-manylinux_2_38_x86_64.whl | CPython 3.11 | abi3 | Linux glibc 2.38+ x86-64 | Details |
Release files / synapse_runtime_sdk-0.2.1-cp311-abi3-manylinux_2_38_x86_64.whl
| Download URL | synapse_runtime_sdk-0.2.1-cp311-abi3-manylinux_2_38_x86_64.whl |
|---|---|
| Size | 8.5 MB |
| Tags | CPython 3.11 Linux glibc 2.38+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
3302972681552f7fd52c1599f43d53a71ecdee73a7eefdff7614dfb2601bba31
|
|
BLAKE2b-256 checksum How to use checksums |
5c94d9d15c88dbb285514bff8fdc16a5e589dd2e58703ead49952a322982ae9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.15
|