babble-bridge
BabbleSim + Zephyr nRF RPC simulation bridge. Provides:
- Test harness — spawn a full BabbleSim simulation from Rust integration tests
- xtask CLI — setup, sim lifecycle, and Docker management commands
- Programmatic API — call setup and spawn functions directly from
build.rsor code
Quickstart for downstream crate authors
1. Add the dependency
Root Cargo.toml:
[]
= ["your-app", "xtask"]
[]
= "0.1.3"
Your crate's Cargo.toml:
[]
= true
2. Create an xtask crate
xtask/Cargo.toml:
[]
= "xtask"
= "0.1.0"
= "2021"
[]
= true
xtask/src/main.rs:
.cargo/config.toml:
[]
= "run -p xtask --"
Platform setup
Linux (native or inside a container)
Also creates tests/sockets/ with restricted permissions (0700).
macOS
BabbleSim only runs on Linux. Use the --container flag — it manages a
persistent Docker container for you:
On first run per workspace this also runs zephyr-setup --prebuilt inside the container
to fetch Linux binaries.
Simulation lifecycle
| Command | Description |
|---|---|
cargo xtask start-sim |
Start PHY + Zephyr RPC server + CGM peripheral + socat bridge (Linux only) |
cargo xtask start-sim --container |
Same, but runs inside a managed container (macOS) |
cargo xtask stop-sim |
Kill simulation processes and clean up BabbleSim IPC |
cargo xtask clean-sockets |
Remove all *.sock files from tests/sockets/ |
Options for start-sim:
--sim-id <id> Socket name and BabbleSim identifier (default: sim)
--sim-dir <path> Directory for the socket file (default: <workspace>/tests/sockets)
--container Build image if needed and run inside a container (macOS)
--log-stream Stream all process output to the terminal with [label] prefixes
--log-dir <path> Write rpc-server.log, cgm.log, phy.log into <path> (truncated each run)
--log-stream and --log-dir can be combined to stream and write files simultaneously.
The socket is created at tests/sockets/<sim-id>.sock.
Connecting to the simulation
From Linux (or inside the container)
use UnixStream;
let socket = connect?;
From macOS
Unix sockets don't cross the OS boundary. start-sim --container automatically
starts a TCP bridge inside the container and publishes it to 127.0.0.1 on your Mac:
TCP bridge ready: connect from macOS at 127.0.0.1:<port>
The port is stable and derived from your workspace path:
use TcpStream;
let stream = connect?;
To run code that needs to reach the socket from macOS, use exec to run it
inside the container instead:
Integration tests
use HashSet;
use UnixStream;
use Path;
use Duration;
use LogOutput;
let tests_dir = new;
let =
spawn_zephyr_rpc_server_with_socat;
// socat needs a moment to start listening after spawn — retry until connectable.
let start = now;
let socket = loop ;
// Run test logic via `socket`, then assert on Zephyr-side log output:
processes.search_stdout_for_strings;
Note:
spawn_zephyr_rpc_server_with_socatreturns as soon as socat is spawned, not when the socket is connectable. Always use a retry loop (as above) before callingUnixStream::connect. Thesim_harness.rsintegration tests use aSimUart::connecthelper that does exactly this.
LogOutput — controlling where process logs go
| Variant | Behaviour |
|---|---|
LogOutput::Off |
Silent — no forwarding (default) |
LogOutput::Stream |
Real-time [label] prefixed output to terminal (bypasses cargo test capture) |
LogOutput::WriteToDir(path) |
Writes rpc-server.log, cgm.log, phy.log into path; files are truncated on every spawn |
LogOutput::Both(path) |
Streams to terminal AND writes to files simultaneously |
// Verbose during interactive debugging:
spawn_zephyr_rpc_server_with_socat;
// Persistent log files, cleared on each run:
spawn_zephyr_rpc_server_with_socat;
Note:
features = ["sim-log"]is now a no-op. Replace it withLogOutput::Streamat the call site.
Tests require Linux — run them inside the container on macOS:
Docker commands
| Command | Description |
|---|---|
cargo xtask docker-build |
Build the dev-container image |
cargo xtask docker-attach |
Open an interactive shell in the container |
cargo xtask docker-run -- <cmd> |
Run a one-off command in a fresh container |
cargo xtask exec -- <cmd> |
Run a command in the persistent sim container |
docker-run creates a fresh container each time (no running sim).
exec targets the persistent container started by start-sim --container,
where the simulation socket is reachable.