Usage & Examples

This guide walks through common workflows using spx_python.client.SpxClient and the utilities in spx_python.helpers. The examples mirror the scenarios exercised in tests/test_basic_spx_python.py, tests/test_helpers.py, and the system-level tests inside spx-examples.


SpxClient behaves like a nested mapping. Indexing descends into sub-components, while attributes inside the attr section appear as properties.

client = spx_python.init(address=BASE_URL, product_key=PRODUCT_KEY)

# Access the models container
models = client["models"]                 # returns another SpxClient

# Descend to an instance and grab the temperature attribute wrapper
sensor = client["instances"]["sensor"]
temperature_attr = sensor["attributes"]["temperature"]

current = temperature_attr.internal_value  # READ
temperature_attr.internal_value = current + 2.5  # WRITE

# Methods exposed by a component become callables
sensor.reset()
sensor.start()

Using get, keys, items

  • client.get() fetches the full JSON payload at the current path.

  • client.get("child", default) behaves like dict.get, catching SpxApiError.

  • for name in client["instances"]: iterates over child component names.

Setting attributes via put_attr

put_attr(relative_path, value) addresses attributes using slash-separated paths. The last segment is the attribute, the preceding segments form the parent path.

put_item performs a raw PUT with an arbitrary payload when you need to update multiple fields at once.


Transparent mode for dry runs

Transparent mode turns the client into a no-op stub that records nothing and simply returns empty structures. Enabling it is useful when unit-testing higher-level logic without a live SPX server.

Inside transparent mode:

  • Indexing returns new transparent clients without performing HTTP.

  • Attribute reads return the sentinel (which is falsy).

  • Writes and method calls are ignored but return {"result": True} to keep call chains intact.

See tests/test_client_unit.py::TestTransparentSentinel for the complete behaviour matrix.


Managing models and instances

The helpers in spx_python.helpers wrap the repetitive steps used across the spx-examples integration tests.

create_instance automatically derives an instance key from the model name (sensor_simsensor_sim, sensor_sim_2, …). These helpers power tests such as tests/test_helpers.py::TestHelperIntegration.


Waiting for state changes

Polling utilities make assertions in integration tests reliable:

  • wait_for_instance(client, "foo_inst", timeout=5) — poll until the instance is visible.

  • wait_for_state(instance, {"RUNNING", "running"}) — poll the .state property.

  • wait_for_attribute_value(instance, "attributes/output", 1.0) — poll until a value matches.

  • wait_seconds(duration) — sleep with short intervals to keep loops responsive.

These helpers are used heavily in the spx-examples device tests (for example the BLE vital signs monitor and Modbus SUTs) to confirm that scenarios and attribute overrides propagate as expected.


Bootstrapping whole systems

bootstrap_model_instance bundles the recurring flow present in end-to-end tests:

The helper returns the SpxClient, the instance wrapper, and a flag indicating whether the model changed (allowing you to reset or recreate dependent instances automatically). This mirrors the setup code in tests like spx-examples/tests/test_ble_vital_signs_monitor_sut.py.


Calling component methods

When a component exposes methods such as start, stop, or custom endpoints defined in your YAML, the client surfaces them as callables that perform POST /method/<name>.

If the call returns JSON, SpxClient hands it back directly. Non-JSON responses result in None. The unit tests cover both cases (tests/test_client_unit.py::test_call_method_value_error_returns_none).


Putting it together

The combination of dictionary traversal, transparent mode, and helper routines lets you write expressive test code:

Everything shown here is battle-tested through spx-python’s own test suite and the sample systems shipped with spx-examples.

Last updated