Writing an application against a mesh

One command gives you a running network and an address to point a client at.

meshbench serve
fixture-fife-strict: 58 nodes, starting firmware

  tcp  127.0.0.1:36205
  node AngusOutlaw1, 56 nodes running real MeshCore firmware

  Point your client at that. Ctrl-C to stop.

Connect to that address and you are talking to a companion node's serial protocol, byte for byte as the firmware produces it. Everything you send crosses a simulated radio to real MeshCore firmware on every other node.

What you are connected to#

your app unmodified TCP or serial socket companion node real firmware its own process its own identity radio fifty-five more nodes, real firmware on each Messages take real airtime, contend for the channel, and are relayed hop by hop.
The endpoint is one node's serial interface. Behind it is a whole network whose behaviour, timing and failures come from the firmware rather than from a mock.

Options#

flageffect
-fixture <path>a different network; the shipped ones are in fixtures/
-node <name>expose a particular companion rather than the first
-seriala virtual serial device instead of TCP, for clients that open a port
-addr 0.0.0.0:4403listen on every interface, so a phone can connect
-quietprint only the address, for scripting

The Companion bench, in the application#

The Companion bench panel, in the App view, does the same thing with a button, and adds what a terminal cannot: the protocol decoded in both directions, whether a client is attached, and faults on demand.

The App view: the Companion bench beside the live event counters and a node's console

One click for both. give me a mesh and an endpoint starts firmware on every node if it is not already running, then serves the first companion over TCP and prints the address. Firmware starts a process per node, so on a large fixture it takes a few seconds and the button says so rather than handing over a port that answers nothing.

Two transports, per companion. TCP for a client that speaks sockets, serial for the many that only know how to open a port. Both carry the firmware's own serial protocol byte for byte - this is not a mock, it is the same bytes the real device sends. The address gets a copy button beside it, because it is going into somebody else's configuration file and retyping a port from a screen is how a digit gets lost.

The Companion bench: transports, the companion table, and the fault buttons

The client column says whether anything is attached. A port that is listening and a port that has a client are different situations, and the difference matters when an application appears to be doing nothing.

Faults#

Drop every client connection takes the listener away with the connection, so the device disappears the way an unplugged cable does - "the device was unplugged", not "the link glitched". An application that reconnects cleanly from that is one that survives a phone going to sleep. Serving again is one click.

Inject a stray frame puts traffic into the stream that the client did not ask for and cannot parse, while it is busy with something else.

Two faults and not a page of them, because two are what the workbench can actually cause today. A button that pretends to inject a fault it cannot is worse than an absent one. Radio-level faults belong to the RF model: move the node, drop its transmit power, or place an emitter beside it and watch what happens to the link.

Testing against it in a pipeline#

meshbench test -fixture fixtures/fixture-fife-strict.json \
  -endpoint tcp:AngusOutlaw1 -junit results.xml

Runs the network for a fixed time, holds the endpoint open for your test to drive, checks the network's own assertions, writes JUnit and exits non-zero if anything failed. Everything is native firmware, so the same seed gives the same run and a failure is reproducible.

If your application is written in Go or Python, the clients give the same thing without leaving the test: a headless session the test owns, a clock it advances, and bench.serve to expose a companion endpoint to dial. Testing your own code covers both arrangements.

What differs from hardware#

The protocol on the wire is identical: this is the firmware's own serial code producing the bytes. What differs is the radio underneath it, which is a model. Links are cleaner than reality because there is no multipath, no body loss and no interference from outside the network, so treat delivery as a best case.

Nothing about the timing is scaled down: a message that takes two seconds to cross four hops here takes about two seconds on hardware, because airtime is computed the way the firmware computes it.

MeshBench documentation. Built from the running application, not from mock-ups. Screenshots are window-only captures; see CLAUDE.md for the rule that keeps them current. Edit this page.