A hundred motes in a grid
A 10×10 grid of Tmote Skys (MSP430 + CC2420) running Contiki-NG's rpl-udp example. DIOs spread out from the root, DAOs climb a DAG up to five hops deep, and the UDP requests start to flow.
Cooja-NG emulates the motes Contiki-NG runs on — Tmote Sky, Z1, CC2538, nRF52840, nRF54L15 — instruction by instruction, on one simulated 802.15.4 radio medium with nanosecond time. It runs Contiki-NG's own Cooja tests headless, without a JVM, and the same seed gives the same run every time.
Each demo is a recording of a real run. CI built the simulator from this site's commit, ran the scenario headless with --ui-record and kept what the web UI would have shown. The player replays the file in this tab: nothing runs on a server. Run it live runs the same scenario in this tab instead: the simulator itself, compiled to WebAssembly, emulating the real firmware while you watch, pause it or drag the motes around.
A 10×10 grid of Tmote Skys (MSP430 + CC2420) running Contiki-NG's rpl-udp example. DIOs spread out from the root, DAOs climb a DAG up to five hops deep, and the UDP requests start to flow.
An MSP430 (Tmote Sky), a Cortex-M3 (CC2538) and a Cortex-M4F (nRF52840), each with its own radio model, on one DAG. The Sky is the root, and both ARM clients complete UDP round trips through it.
A 4×4 grid of TI CC2538 motes — Cortex-M3 with the on-chip 802.15.4 radio — around a root in the centre. The overlapping circles are each mote's radio range in the unit-disk medium.
Two Seeed XIAO nRF54L15s (Cortex-M33). Each node's Non-secure world runs Contiki-NG and reaches the radio through SG veneers into the Secure world's driver — and they still join one DAG and exchange UDP.
Contiki-NG's 6tisch simple-node: the coordinator sends enhanced beacons, the second node scans, associates and keeps its sync. A time-slotted MAC only works if the emulated radio's timing is right.
The built-in energest plugin turns each mote's radio and CPU states into an energy estimate, in the spirit of Cooja's PowerTracker, and draws it as a live panel. The recording keeps the panel too.
Zephyr's stock echo_server, unmodified, and a Contiki-NG node that sends it datagrams of 16 to 640 bytes and checks every echo. Neighbor Discovery finds the server; from 128 bytes up each datagram crosses as 6LoWPAN fragments, reassembled by the other OS.
A stock RIOT node, driven from its own shell, joins the RPL network a Contiki-NG node roots, takes its address from the root's prefix, then pings it (300-byte pings go as fragments) and trades UDP messages with it. Two RPL implementations, one DODAG.
In the player: the scrubber seeks, the slider sets the speed (simulated seconds per second), Timeline shows each mote's radio activity, and the Packets tab decodes every frame. A hidden tab pauses playback until you come back.
cngsim runs a simulation from a short YAML file and prints what the nodes print, the checks and a verdict, or opens it in your browser. The examples, the firmware they run and the guide come in the same download.
bin/ on your PATH, or build from source: make && make install PREFIX=~/.local.cngsim examples lists them; cngsim run rpl-udp-sky runs one headless, with an exit code CI understands.--ui opens the browser, paused. Drag nodes, add and remove them, type into a node's console, and save the setup as YAML.cngsim new writes a commented setup from a template, on any board, in a grid, line, circle or at random. Point it at your own Contiki-NG builds with board:.$ cngsim run rpl-udp-sky
cooja-ng 0.4.0 · RPL-UDP on two Tmote Skys · 2 nodes · seed 42
19.000 [Node 2/MSP430] Sending request 0 to fd00::212:7401:1:101
✓ "Sending request" on node 2 (19.000 s)
19.019 [Node 1/MSP430] Received request 'hello 0'
✓ "Received request" on node 1 (19.019 s)
19.063 [Node 2/MSP430] Received response 'hello 0'
…
✓ "Received response" ×3 on node 2 (38.203 s)
PASSED · 38.2 s simulated in 0.04 s
$ cngsim run rpl-udp-sky --ui
Web UI: http://localhost:8080/
Paused: press Play (or Space) in the browser, or Enter here, to start.
$ cngsim new rpl-udp --board nrf52840-dk -n 9 --layout grid -o my-net.yaml
Wrote my-net.yaml: 9 nrf52840-dk nodes, grid layout, 45 m radio range.
Contiki-NG's simulation tests are .csc files for Java Cooja. Cooja-NG converts each one, builds the firmware it needs from your tree, runs it with the test's own JavaScript and reports PASS or FAIL — from one binary, with no JVM and no GUI, roughly an order of magnitude faster than Cooja with MSPSim.
tools/run-cooja-tests.sh takes CONTIKI_DIR (5.2 or develop), builds and caches the firmware, and runs everything, one category or one .csc.--seed N is Cooja's --random-seed. The same seed gives a byte-identical simulation, and the project's CI diffs every engine change against main to keep it that way..csc feature that is not implemented, a broken firmware build, a pattern that matches nothing: each is an error with a reason and a non-zero exit, never "0 tests, all OK".SIMULATOR=cooja-ng patch for Contiki-NG's own make -C tests/… flow.--script runs a command script against the simulation — send input, expect output, wait-until a condition — and the exit code says what failed: what a CI job, or a coding agent, needs from a test bench.# a Contiki-NG checkout next to this repository $ export CONTIKI_DIR=~/contiki-ng $ tools/run-cooja-tests.sh === Cooja Test Suite (csim) === RUN 07-simulation-base/01-hello-world-sky PASS (0s) RUN 07-simulation-base/02-ringbufindex PASS (1s) RUN 09-ipv6/01-ping-lla-csma-w-rpl PASS (1s) RUN 14-rpl-lite/01-rpl-up-route PASS (1s) RUN 15-rpl-classic/07-rpl-random-rearrangement PASS (6s) … SKIP 17-tun-rpl-br/01-border-router-cooja (filtered) … === Results === Total: 93 Passed: 85 Failed: 0 Skipped: 8 Errors: 0 # the 8 skips are the border-router tests, which need a TUN # device: --with-tun (root, or setcap on tunslip6) runs all 93 $ tools/run-cooja-tests.sh 14-rpl-lite --seed 3
Each CPU is an interpreter (with a JIT for hot MSP430 and Thumb blocks) and each SoC a model of its peripherals, down to the radio's per-byte timing. Everything shares one event queue and one radio medium.
Each release ships prebuilt binaries for Linux x86-64 and macOS (Intel and Apple Silicon), with checksums and a build-provenance attestation per tarball.
Cooja-NG, usable without building it from source: cngsim takes you from the download to a running simulation in three commands, with commented examples, layouts that place many nodes at once, and a web UI that edits the running network and saves it as YAML. The same C code runs in the browser on the original firmware, held to the native build byte for byte, behind this site's live demos. The CC1352R1 and CC1312R7 LaunchPads join, Contiki-NG talks to Zephyr and to RIOT in two interop demos, and configs are checked harder — read Changed in the notes before upgrading.
A command shell and script engine for testing firmware through its own console, run recording and replay (this site), the nRF54L15's TrustZone-M enforced the way a Seeed XIAO enforces it, Renode co-simulation, the simulator as a library, FreeBSD, and a kernel wakeup path that no longer scales with the node count. The three release binaries give byte-identical simulation output.
YAML as the primary config format, external motes for emulators that keep their own clock (esp32sim's ESP32-C6), and a kernel fix that made the border-router traceroute test pass on Linux.
The first prebuilt binaries, the first release to pass Contiki-NG 5.2's complete Cooja suite (93 of 93), and a JIT for Cortex-M.
Add --ui-record to any run and you get the file these demos play: the web UI's stream, with the simulation unchanged. Put it next to player.html (the repository's ui/index.html) on any static host and open player.html?replay= plus its name.
./build/test_runner test configs/test-mixed-platform-rpl.yaml --ui-record mixed.json