Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Using SiLA2 Devices with MADSci

Status: Experimental. SilaNodeClient is an early preview of native SiLA2 support in MADSci. The client surface, optional-dependency name, and binary/error handling may change as the broader migration lands. The umbrella project and design proposal are tracked in openspec/changes/sila2-native-node-design/ (issue #293).

This notebook demonstrates how to use the SilaNodeClient to communicate directly with SiLA2-based laboratory instruments from MADSci.

This notebook also doubles as the SiLA validation harness. It is executed end-to-end via papermill by just validate_nb_sila, and uses assert statements throughout to verify behavior against the live sila_example_server. If you’re reading it as a tutorial, mentally treat the asserts as “this is what the result should look like.”

What You’ll Learn

  1. Connecting to a SiLA2 server using sila:// URLs

  2. Discovering features and commands via get_info()

  3. Checking server status via get_status()

  4. Reading properties via get_state()

  5. Executing unobservable (synchronous) commands

  6. Executing observable (long-running) commands with await and polling

  7. Handling binary data responses as ActionFiles

  8. Error handling for unreachable servers

Prerequisites

This notebook requires:

  • The madsci.client[sila] extra installed (pip install "madsci.client[sila]"), which pulls in the sila2 SDK at a compatible version

  • The SiLA example server running on localhost:50052 (provided by the example lab compose stack)

Connecting to a SiLA2 Server

The SilaNodeClient uses sila://host:port URLs, just like RestNodeClient uses http:// URLs. The workcell manager’s find_node_client() automatically routes sila:// URLs to SilaNodeClient.

Server Introspection: get_info()

The get_info() method discovers the server’s features and commands, returning a NodeInfo with ActionDefinition entries for each SiLA command. Action names use dot notation: FeatureName.CommandName.

Server Status: get_status()

The get_status() method probes the server’s connectivity and reports whether it’s busy, errored, or disconnected.

Reading Properties: get_state()

The get_state() method reads all SiLA property values from the server, returning a dict keyed by FeatureName.PropertyName.

Unobservable Commands: Synchronous Execution

Unobservable SiLA commands execute immediately and return the result. The action_name uses dot notation (Feature.Command) or short form if unambiguous.

Observable Commands: Blocking with await_result=True

Observable SiLA commands are long-running. With await_result=True (the default), send_action() blocks until the command completes.

Observable Commands: Polling with await_result=False

With await_result=False, send_action() returns immediately with RUNNING status. You can then poll with get_action_status() and retrieve results with get_action_result().

Binary Data and ActionFiles

SiLA commands can return binary data (bytes). The SilaNodeClient automatically:

  1. Writes bytes to disk as .bin files in .madsci/sila_files/{action_id}/

  2. Populates ActionResult.files as an ActionFiles instance with file paths

  3. Base64-encodes the bytes in json_result for lightweight inspection

The example server’s GenerateData command returns a deterministic byte sequence, making it easy to verify the round-trip.

Error Handling: Unreachable Server

When a SiLA server is unreachable, get_status() returns a NodeStatus with errored=True and disconnected=True rather than raising an exception.

Cleanup