
OPC UA Simulator
A virtual device lab to simulate OPC UA device behavior, edge cases and failures — so you can test faster, automate scenarios and ship integrations with confidence.
-
Scenario-driven testing (faults, delays, reconnect storms)
-
Snapshots for reproducible debugging & regression
-
Automation-ready for CI/CD pipelines
SPX platform overview
SPX is the engineering environment behind this OPC UA simulation — a portable, Docker-based virtual device lab for building and testing realistic device behavior. It supports multiple industrial protocols, code-defined simulations, physics-driven dynamics, and scenario-based validation, so you can run model-in-the-loop style workflows without a physical lab.
Everything is designed for reproducibility and automation, with an LLM-friendly project structure that helps you extend models, scenarios, and tests faster — from engineers, for engineers.




Technical capabilities
These capabilities focus on repeatability, protocol realism, and automation—so you can ship embedded integrations with confidence.
Protocol simulation for embedded software testing
Protocol simulators (including OPC UA) are often the missing link in embedded software testing. They let you validate firmware behavior, integration flows, and edge cases without physical hardware, while keeping test environments deterministic and CI-ready. If you want the full workflow—how we combine simulation models, runtime smoke checks, and automation with spx-python—see our overview here: Embedded Software Testing with SPX.
Related resources
SPX helps you emulate an OPC UA server in a way that matches real client expectations:
• Address space modeling — define nodes, hierarchies, and realistic data organization.
• Namespaces & NodeIds — keep identifiers stable for repeatable client integration.
• Browse & discovery behavior — validate browsing logic and client navigation.
• Read/Write semantics — test value updates, write access, and client-side validation paths.
• Subscriptions & monitoring — emulate monitored items and update flows clients rely on.Use this to verify not only “can I connect?”, but whether your client behaves correctly across real-world server structures.
communication:
- opcua:
endpoint: "opc.tcp://opcua-server:4840"
security_policy: "None"
security_mode: "None"
bindings:
- name: motor_speed
node_id: "ns=2;s=Motor.Speed"
direction: outbound
value_codec: float
read_attribute: "#attr(motor_speed_rpm)"
- name: start_command
node_id: "ns=2;s=Motor.Start"
direction: inbound
value_codec: bool
write_attribute: "#attr(cmd__start)"When something goes wrong in production, you need to see exactly what happened. SPX supports visibility into OPC UA interactions so you can debug with confidence:
• Read/Write/Subscribe traces — understand how your client interacts with the server.
• Per-node visibility — pinpoint which variables/methods were accessed and when.
• Timing-aware debugging — validate update intervals, delays, and behavior under load.
• Regression-friendly comparisons — compare runs to detect subtle behavior changes.This makes it practical to reproduce integration bugs and confirm fixes with evidence.

SPX is not only “protocol messages” — it can model realistic device behavior that drives OPC UA values over time:
• Environment-driven dynamics (e.g., temperature trends, pressure changes, occupancy effects).
• Noise & drift — emulate sensor imperfections and real signal behavior.
• State machines — model startup, normal operation, degraded modes, and faults.
• Engineering realism — validate filtering, thresholds, alarms, and UI logic against lifelike signals.This capability is shared across SPX protocols and packs, so your tests stay realistic even when you switch transports.
actions:
# Environment-driven dynamics: warm-up ramp
- function: $out(temperature_c)
name: Warmup Ramp
params:
start_c: 20.0
end_c: 45.0
t0: 0.0
t1: 120.0
call: |
(lambda t:
start_c + (end_c - start_c) * min(1.0, max(0.0, (t - t0) / max(0.1, t1 - t0)))
)($attr(timer.time))# Noise & drift: realistic sensor imperfections
- noise: $out(temperature_c)
name: Temperature Noise
std: 0.02
mode: proportional
- function: $out(pressure_bar)
name: Pressure Drift
params: {drift_per_s: 0.0002}
call: $out(pressure_bar) + drift_per_s * $in(cycle_time_s)# State machine: startup → normal → degraded
- function: $out(device_state)
name: Device State Machine
params:
t_startup: 30.0
t_degraded: 180.0
call: |
(lambda t:
"startup" if t < t_startup else
"normal" if t < t_degraded else
"degraded"
)($attr(timer.time))# Engineering realism: alarms based on thresholds
- function: $out(alarm_overtemp)
name: Overtemp Alarm
call: 1 if $out(temperature_c) > 50.0 else 0
Scenario-driven simulation lets you test what usually breaks OPC UA integrations:
• Predefined scenarios to reproduce complex conditions consistently.
• Sequenced events — controlled transitions like normal → degraded → offline → recovery.
• Fault injection — simulate bad data, unexpected changes, or timing anomalies.
• Deterministic outcomes — replay the same scenario across machines and teams.Use scenarios to validate: reconnect behavior, subscription recovery, data quality handling, and client-side resiliency.
scenarios:
opcua_recovery_cycle:
display_name: "OPC UA recovery cycle"
duration: 120.0
conditions:
# normal → degraded
- if: $attr(timer.time) < 30.0
actions:
- function: $out(device_state)
call: "normal"
- function: $out(quality_code)
call: 0
- if: ($attr(timer.time) >= 30.0) and ($attr(timer.time) < 60.0)
actions:
- function: $out(device_state)
call: "degraded"
- function: $out(quality_code)
call: 100# offline (fault injection)
- if: ($attr(timer.time) >= 60.0) and ($attr(timer.time) < 90.0)
actions:
- function: $out(device_state)
call: "offline"
- function: $out(quality_code)
call: 200# recovery
- if: $attr(timer.time) >= 90.0
actions:
- function: $out(device_state)
call: "normal"
- function: $out(quality_code)
call: 0
SPX projects can be structured to work efficiently with LLM-assisted development — so you can scale simulation content while keeping it consistent:
• LLM-ready specs describing models, nodes/bindings, scenarios, and expected behavior.
• Consistent conventions for packs, simulators, and integration tests.
• Spec-first iteration — refine behavior in the spec, then generate/update implementations.
• Reviewable outputs — LLM-generated changes are easier to validate when behavior is testable.
• Automation alignment — specs + tests support a tight loop: generate → run scenarios → verify → iterate.This makes it practical to add new device models and scenarios faster without sacrificing quality or reproducibility.
SPX is designed to fit modern engineering pipelines:
• Python client wrapper to control simulations programmatically from tests.
• CI/CD integration — start simulators, run scenarios, assert outcomes, collect logs automatically.
• Docker-based distribution for consistent environments across dev machines and build agents.
• Repeatable baselines — the same simulator behavior locally and in CI.This enables practical integration testing: bring up the simulator, connect your OPC UA client, run a scenario, and verify behavior — all as part of your pipeline.





