Using spx-python for Simulation
spx-python is a Pythonic wrapper around the SPX Server API. It exposes the SPX system as a dictionary-like tree so you can build, control, and inspect simulations directly from Python. With spx-python you can:
Create models and instantiate them,
Read/write attributes (internal/external),
Control simulation time deterministically,
Run Model-in-the-Loop (MiL) tests, inject faults, and verify outcomes.
Key idea: your production app (SUT) talks to the simulation over the real protocol (MQTT/HTTP/…); meanwhile your tests use spx-python as a control channel to set parameters, advance time, and check results.
Purpose
spx-python provides deterministic, programmable control over SPX simulations:
Build systems programmatically (models → instances → connections),
Manipulate parameters and states during execution,
Advance time explicitly for reproducible scenarios,
Automate MiL tests and edge-case validation,
Prototype scenarios quickly without hardware.
Installation and Setup
Install from PyPI:
Connect to a running SPX Server:
Core Concepts Recap (client view)
Models – reusable templates. Create/replace with:
client["models"]["MyModel"] = {...}Instances – live objects created from models:
client["instances"]["sensor"] = "MyModel"Attributes – named values on instances, accessed via:
inst["attributes"]["temperature"].internal_value(read/write)inst["attributes"]["temperature"].external_value(read/write)Connections – links between attributes across instances:
client["connections"]["c1"] = {"from": "#ext(a.b)", "to": "#in(c.d)"}Time & run loop – you advance time and run explicitly:
inst["timer"]["time"] = t; client.prepare(); client.run()
Quick Start Example (end‑to‑end)
Minimal heater model that raises temperature based on power:
What to notice
You assign a Python dict to
client["models"]["Heater"].You instantiate by assigning the model name under
client["instances"].You set inputs via
internal_valueorexternal_value.You drive time through
instance["timer"]["time"]and callclient.run().You read outputs from
external_value.
Attribute Access Cheat Sheet
Conventionally, inputs are written to
internal_valueand reported/observable values are read fromexternal_value. Your model can map them as needed.
Multiple Instances and Connections
Create two instances and wire them together:
Using spx-python in MiL Tests (pytest)
Deterministic MiL test that advances time and asserts behavior:
Your SUT can run alongside this test and communicate with the model over the real protocol. The test remains in full control of time and parameters via spx-python.
Fault Injection and Edge Cases
Inject a sensor fault mid-run and verify system response:
Hot‑Reloading Components (server endpoint)
If your server exposes an admin reload endpoint (e.g., system.reload), call it before creating new instances to make freshly registered components available. spx-python focuses on the system tree; for custom admin endpoints use requests:
Best Practices
Deterministic time: always set
instance["timer"]["time"]beforeclient.run(). Keeptimer.dtconsistent for repeatability.Small, focused models: compose simple units for clearer tests and faster iterations.
Separate channels: let the SUT use the protocol channel; keep spx-python for control/observation.
Version scenarios: store model defs and test seeds in your repo for stable CI.
Further Reading
API v3 Reference (server endpoints specific to your deployment)
Last updated

