Technical Documentation

MeshCore message formats & payloads

Technical deep-dive into the structure of MeshCore messages, Protobuf encoding and payload formats for efficient LoRa communication

How MeshCore messages are structured

MeshCore uses an efficient message structure to send data over the LoRa mesh network. Each message consists of a header with metadata and a payload with the actual content. By using Protocol Buffers (Protobuf), messages remain compact and structured.

The message formats are designed for low-bandwidth communication. LoRa has limited throughput (typically 100-300 bytes per message), so efficiency is crucial. MeshCore compresses data intelligently and uses binary encoding instead of text-based formats like JSON.

In this technical guide, we explain how MeshCore messages are structured, what message types exist, and how payloads are encoded for optimal performance in the mesh network.

Protocol Buffers (Protobuf) structure

MeshCore uses Google's Protocol Buffers for message serialization. Protobuf is a binary format that is much more efficient than JSON or XML. An example of a MeshCore message definition:

message MeshPacket {
  uint32 from = 1;      // Sender node ID
  uint32 to = 2;        // Receiver node ID
  uint32 id = 3;        // Unique message ID
  bytes payload = 4;    // Encoded data
  uint32 hop_limit = 5; // Max number of hops
  bool want_ack = 6;    // ACK request
  uint32 rx_time = 7;   // Reception timestamp
}

Each field has a tag number (1, 2, 3, etc.) for compact encoding. Protobuf only stores fields that have a value (optionals), which saves space. A typical MeshCore message is only 20-50 bytes without payload.

MeshCore message types

๐Ÿ’ฌ

TEXT_MESSAGE

Text messages between users. Max 200 characters plain text. Most commonly used message type for communication.

๐Ÿ“

POSITION

GPS coordinates (latitude, longitude, altitude). Updates location of nodes on the map. Sent periodically.

๐Ÿ“Š

TELEMETRY

Sensor data: battery voltage, temperature, humidity. For monitoring nodes and environmental data.

โš™๏ธ

NODEINFO

Node information: name, hardware model, firmware version. Sent at startup and periodically for network discovery.

๐Ÿ”—

ROUTING

Routing information and network topology updates. Used by the flooding algorithm for efficient message delivery.

๐Ÿ“ก

ADMIN

Administrative commands: change configuration, reboot, channel settings. Only for authorized nodes.

Payload structure and encoding

Packet header (overhead)

Each MeshCore packet has a header of ~20 bytes with metadata:

  • <strong>From/To</strong> - Node IDs (32-bit integers)
  • <strong>Packet ID</strong> - Unique number for duplicate detection
  • <strong>Hop limit</strong> - Number of remaining hops (default 3, max 7)
  • <strong>Flags</strong> - want_ack, encrypted, etc.

Payload data

The payload contains the actual content, encoded as Protobuf bytes. Maximum payload size is ~230 bytes (depending on LoRa spreading factor). Encrypted payloads use AES-256 with a shared channel key.

Technical specifications

Parameter Value Description
Max packet size 256 bytes LoRa PHY layer limit (SF7/8)
Header overhead ~20 bytes Protobuf header with routing info
Max payload ~230 bytes After deducting header overhead
Text message max 200 chars UTF-8 encoded, practical limit
Encoding format Protobuf 3 Binary, backward compatible
Encryption AES-256-CTR Per-channel PSK encryption

Benefits of MeshCore message formats

โšก

Extremely compact

Protobuf encoding is 3-10x smaller than JSON. Essential for low-bandwidth LoRa communication.

๐Ÿ”„

Backward compatible

New fields can be added without breaking old clients. Protobuf schema evolution.

๐Ÿ›ก๏ธ

Type-safe

Strict type checking prevents parsing errors. Fewer bugs than loosely-typed formats.

๐Ÿš€

Fast parsing

Binary format is much faster to parse than text-based formats. Important for low-power devices.

๐ŸŒ

Multi-platform

Protobuf libraries available for C++, Python, JavaScript, Go, etc. Easy to build clients.

๐Ÿ“ฆ

Extensible

Custom payload types can be easily added for specific use cases.

Frequently asked questions

Why does MeshCore use Protobuf instead of JSON?

Protobuf is 3-10x more compact than JSON and faster to parse. LoRa has very limited bandwidth (~300 bytes/s), so every byte counts. JSON would have too much overhead for a mesh network.

What is the maximum length of a text message?

Text messages are limited to 200 characters. This fits comfortably within the ~230 byte payload limit (UTF-8 encoding). Longer messages must be split.

Are all messages encrypted?

No, only messages on private channels with a PSK (Pre-Shared Key) are encrypted with AES-256. Public channels are unencrypted. You can configure encryption per channel.

Can I add custom message types?

Yes, MeshCore supports custom port numbers for your own payloads. You can define your own Protobuf messages and send them via port numbers 256-511. See the plugin development documentation.

How do I know which message format a node supports?

Each node sends a NODEINFO message at startup with its firmware version. Protobuf is backward compatible, so new fields are ignored by old firmware. Forward compatibility is guaranteed.

What happens if a message is too large?

Messages larger than ~230 bytes are truncated or rejected by the firmware. You will receive an error. Split long data into multiple messages or use data compression.

Start with MeshCore development

Now that you know how MeshCore messages are structured, you can start developing your own applications and plugins.