Skip to main content

Choosing an Integration Path

There is more than one way to get your own code onto a Meshtastic mesh, and the right one depends on where you want the boundary between your code and the firmware to sit. This document compares the options so you can pick before you start building. For the protocol details of each, see the client API and module API documents.

The four approaches

Module inside the firmware

You write a MeshModule subclass, it is compiled into the firmware, and it receives packets on a port number you choose. This is the deepest integration available and the one to reach for when your feature belongs on the device itself: it can see every packet, send its own, and use anything else the firmware provides.

You ship a firmware build rather than a separate application, and your code follows the firmware release cycle. See the module API document to get started.

Client running inside the firmware

The client API is not only for external hardware. PacketAPI in src/mesh/api/PacketAPI.h is a PhoneAPI subclass that is also an OSThread, bound to a shared queue rather than to a UART. Your task exchanges the same ToRadio and FromRadio protobufs with the firmware beside it, on the same processor and with no wire in between.

This is how device-ui is built. Its IClientBase interface is the whole contract your code implements: send a ToRadio, receive a FromRadio. Because the interface also has serial, TCP, Ethernet and Bluetooth implementations, an application written against it runs either inside the firmware or on a second processor wired to a node, without changing.

Nothing is serialized when it runs in process. The queue carries the structure itself.

External client over the client API

Your code runs on separate hardware, or on a phone or PC, and talks to a node over Serial, TCP or Bluetooth using the client API. The node stays on stock firmware, which means no custom build to maintain and no firmware release to track.

Libraries exist for several languages, including Meshtastic-arduino for microcontroller clients, and the Python, JavaScript and Android libraries for larger hosts.

An independent implementation

Rather than talking to a node, your device can speak the mesh protocol itself. libmeshtastic-leaf is one such implementation, built on RadioLib, which puts framing, channel and PKI encryption, the region tables and the transmit policy into a library your sketch drives directly.

There is no Meshtastic firmware anywhere in this arrangement, so there is also nothing to inherit. A leaf node of this kind sends and receives but never relays, and it has no node database, no modules and no configuration UI. Anything the firmware would have provided is yours to write.

note

Only the first three approaches produce a Meshtastic node. An independent implementation participates in the mesh but does not extend it, because it does not rebroadcast for its neighbours.

What each approach provides

"Via the node" means the attached or surrounding firmware performs it on your behalf, which is usually what you want, but it also means you take its behaviour as given.

CapabilityFirmware moduleIn-firmware clientExternal clientIndependent
Runs without a second processorYesYesNoYes
Runs on stock firmwareNoNoYesNot applicable
Send on any port numberYesYesLibrary dependentYes
Receive on any port numberYesYesYesYes
Signal strength and SNR per packetYesYesLibrary dependentYes
Channel and PKI encryptionVia the nodeVia the nodeVia the nodeYours
Region, duty cycle and carrier senseVia the nodeVia the nodeVia the nodeYours
Routing and rebroadcastVia the nodeVia the nodeVia the nodeNo
Node databaseVia the nodeYesYesNo
Read and change node configurationDirect accessAdmin messagesLibrary dependentNot applicable
Position, telemetry and other modulesVia the nodeVia the nodeVia the nodeNo
Identity and keysThe node'sThe node'sThe node'sYours

Choosing

Start with a firmware module when the feature belongs to the device and you are willing to ship firmware. Most of the functionality shipped with Meshtastic is built this way, and it is the path with the most examples to copy from.

Choose an in-firmware client when you are writing a whole application rather than a feature, such as a user interface or a bridge, and you want it to be portable between running on the node and running on a second processor.

Choose an external client when the node should stay on stock firmware, when your code belongs on a phone or PC, or when the language you want is not C++.

Choose an independent implementation when a whole node is more than the job needs: a sensor that must speak to the mesh on its own, on one processor and one battery, with no second board.

note

Whichever you pick, an application sending its own traffic needs a port number. See port numbers before you choose one.