
BACnet Simulator
A virtual device lab to simulate BACnet device behavior, edge cases and failures — so you can test faster, automate scenarios and ship integrations with confidence.
-
Scenario-driven testing (discovery issues, timeouts, flaky networks)
-
Snapshots for reproducible debugging & regression
-
Automation-ready for CI/CD pipelines
SPX platform overview
SPX is the engineering environment behind this BACnet simulator — 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.
SPX helps you emulate BACnet devices in a way that matches real client expectations:
• Objects & properties — model realistic object sets and property behavior for device-like integrations.
• Workflows — validate device discovery and identification flows used by BACnet tools and BMS platforms.
• Read/Write semantics — test property reads, writes, and client-side validation paths.
• Device-like structure — consistent naming and predictable behavior for repeatable integration tests.
• Edge-case readiness — exercise failure modes that often appear in real deployments.Use this to verify that your BACnet client/BMS behaves correctly across real-world device shapes.
communication:
- bacnet:
host: 0.0.0.0
port: 47840
device:
instance_id: 4101
vendor_id: 999
name: "SPX BACnet Demo Device"
model_name: "spx-server"
description: "Simple BACnet demo for discovery/read/write checks"
timing:
poll_interval: 0.5
poll_jitter: 0.05
objects:
room_temperature:
type: analogInput
instance: 1
properties:
presentValue:
read: "#attr(room_temp_c)"
units: "degreesCelsius"
temperature_setpoint:
type: analogValue
instance: 2
properties:
presentValue:
read: "#attr(temp_setpoint_c)"
write: "#attr(temp_setpoint_c)"
units: "degreesCelsius"When integrations break, observability is everything. SPX supports logging that helps you understand what happened and why:
• Per object/property visibility — inspect what was read/written and when.
• Structured logs suitable for debugging and reporting (payloads, timing, direction).
• Repeatable runs — compare logs between runs to detect regressions.
• Integration-friendly evidence — logs can support QA workflows and troubleshooting.This makes it practical to reproduce bugs and confirm fixes with confidence.

SPX is not only protocol simulation — it can model device behavior as it would occur in the real world:
• Environmental dynamics (e.g., temperature trends, occupancy patterns, weather-driven changes).
• Noise and signal imperfections — emulate sensor noise, drift, or jitter.
• Device response logic — state machines and behavior rules that match real equipment.
• More realistic testing — validate filtering, thresholds, alarms, and UI logic.This capability is shared across SPX protocol modules and packs — so your tests stay realistic even when you switch protocols.
actions:
# Environmental dynamics: occupancy trends + outdoor influence + HVAC impact.
- function: $in(occupancy_count)
name: trend_occupancy
step: 0.2
call: (
$in(occupancy_target)
if abs($in(occupancy_target) - $in(occupancy_count)) <= step
else $in(occupancy_count) +(step if $in(occupancy_target) > $in(occupancy_count) else -step)
)
# Sensor imperfections: slow drift + random noise/jitter.
- function: $in(sensor_bias_c)
name: sensor_drift
call: max(-0.6, min(0.6, $in(sensor_bias_c) + 0.002 *($in(outdoor_temp_c) - $in(room_temp_c))))
- function: $in(room_temp_measured_c)
name: apply_sensor_bias
call: $in(room_temp_c) + $in(sensor_bias_c)- noise: $out(room_temp_measured_c)
name: room_temp_sensor_noise
std: 2.5e-2
mode: proportionalScenario-driven simulation lets you test what usually breaks BACnet integrations:
• Predefined scenarios bundled with packs (e.g., discovery issues, flaky networks, device restarts).
• Sequenced events — controlled transitions like normal → degraded → offline → recovery.
• Fault injection — simulate conditions that are hard to reproduce with physical devices.
• Deterministic outcomes — reproduce the same scenario across machines and teams.Use scenarios to validate: discovery robustness, polling behavior, alerting, and edge-case parsing.
scenarios:
bacnet_discovery_degraded_offline_recovery:
display_name: "BACnet: normal -> degraded -> offline -> recovery"
description: |
Deterministic BACnet resilience test covering discovery changes,
degraded polling behavior, simulated restart/offline conditions,
and recovery to baseline operation.
duration: 48.0
conditions:
- if: $attr(timer.time) < 12.0
actions:
- overrides:
communication.bacnet.device.instance_id: 4101
communication.bacnet.device.name: "SPX BACnet Demo Device"
communication.bacnet.timing.poll_interval: 0.5
communication.bacnet.timing.poll_jitter: 0.0
fail_on_missing: false
- set: $in(device_fault)
value: 0
- set: $in(device_health_mode)
value: 1
- set: $in(temp_setpoint_c)
value: 22.5- if: ($attr(timer.time) >= 12.0) and ($attr(timer.time) < 24.0)
actions:
- overrides:
communication.bacnet.timing.poll_interval: 2.0
communication.bacnet.timing.poll_jitter: 0.25
fail_on_missing: false
- set: $in(device_fault)
value: 1
- set: $in(device_health_mode)
value: 2
SPX is designed to fit modern test pipelines:
• Python client wrapper to drive simulations programmatically from tests.
• CI/CD integration — start simulations, run scenarios, assert outcomes, and collect logs automatically.
• Docker-based distribution for consistent environments across developer machines and build agents.
• Repeatable test setups — the same simulator behavior locally and in CI.This enables practical integration testing: bring up the simulator, connect your BACnet tool/BMS/client, run a scenario, and verify behavior — all as part of your pipeline.
SPX projects can be structured to work efficiently with LLM-assisted development, so you can extend simulations faster while keeping them consistent:
• LLM-ready specs describing device models, protocol behavior, scenarios, and expected outcomes.
• Consistent conventions for packs, device models, and integration tests.
• Spec-first iteration — refine specs first, then generate or update models and tests from the specification.
• Outputs — LLM-generated changes are easy to validate because behavior is defined and testable.
• Automation alignment — specs + tests support a tight loop: generate → run scenarios → verify → iterate.This makes it practical to scale simulation content while maintaining quality and reproducibility.
Protocol simulation for embedded software testing
Protocol simulators (including BACnet) 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.





