Skip to content

Protocol overview

Status: LowMesh has not been publicly released. This repository documents the current LowMesh mesh specification: verFlags VERSION bits 15–14 = 0b10 identify the current header layout (not a public API v1/v2 release), a dynamic 16-byte minimum base header (20 bytes with HAS_DST_ID), mandatory on-wire sessionId (4 bytes LE at offset 0x09), 16-bit channelHash and messageId, AES-256-CCM-4 as the required MIC mode (optional CCM-8), and stateless dumb-pipe repeaters that forward using flood and strict on-wire routes with RAM duplicate suppression — not distance-vector tables.

LowMesh is a packet-switched mesh protocol for sub-GHz or 2.4 GHz ISM radios (implementation-defined), designed for low airtime, clear crypto boundaries (AES-256-CCM-4 on named channels and DMs), optional gateways with an explicit internet uplink boundary, and large payloads via fragmentation and recovery.

The protocol is specified at the application framing and forwarding layer. Physical layer parameters (spreading factor, bandwidth, symbol rate) are configured as a radio profile in device NVM and advertised in NODE_ADVERT; see LoRa & hardware.

Integrity: Packet layout documents LoRa PHY CRC and AES-256-CCM-4 (4-byte MIC on the application tail for all channels, including 0x0000). Embedded storage (C++) shows how firmware mirrors camelCase field names in the lowmesh namespace using parsed header views (ParsedBaseHeader, modular tail parsers), not a single legacy packed struct.

Architectural summary

High-level roles and paths

LayerResponsibility
PHY / MACChannel access, preamble, LoRa CRC16 (modem), optional whitening — see Packet layout.
LinkNeighbor discovery, link metrics, optional time sync slots.
NetworkHop limit (hopControl / wire ttlRaw, policy-capped by HASH_SIZE — see Routing); TTL-capped flood and optional strict on-wire routes; no predictive next-hop RAM tables.
TransportmessageId (16-bit), optional fragment block, ACK / FRAG_NACK — see Fragmentation.
ApplicationpayloadType selects the inner body: TEXT_UTF8 / POSITION_CORE / TELEMETRY_BASIC, PAYLOAD_BODY_V2, admin (0x91/0x92), etc. — see Payloads.

Design principles

  1. Explicit roles — Primary roles are Client, Repeater, and Gateway. Profiles (e.g. Standard Client, Sensor) describe behavior within a role.
  2. Stateless repeaters — Third-party relay is a dumb pipe: decrement TTL where applicable, apply duplicate suppression, optionally extend routing blocks on floods; no mesh-wide distance-vector route cache.
  3. Channel policy — The header carries channelHash (LE uint16_t, truncated from the normative digest — see Channels & security). channelHash == 0x0000 is the default community domain: AES-256-CCM-4 with ROM defaultCommunityPsk32 (encrypted/authenticated on-air, but not private against other LowMesh devices because the key is globally shared). Other hashes identify named + PSK-bound virtual wires (or DM sessions); receivers resolve keys, then decrypt with the matching AES-256 key — see Crypto keys.
  4. Observable I/O — The same framed bytes are visible on USB CDC and GATT (BLE), with a documented hex-oriented API for test and integration.

Packet envelope (current dynamic base)

All multi-byte integers below are little-endian unless a specific profile says otherwise.

FieldSizeDescription
verFlags2Version (15–14), optional blocks, FLOOD, HASH_SIZE, etc. — see Packet layout.
channelHash2LE uint16_t — see Channels & security. 0x0000 = default community (ROM defaultCommunityPsk32, still CCM-4).
hopControl (ttlRaw)1Hop / relay semantics — see Routing.
srcId4Source nodeId32.
sessionId4Mandatory transport session (LE uint32 at offset 0x09). Persisted in NVM; used in CCM nonce and duplicate/replay keys — see Channels & security.
dstId0 or 4Present only if HAS_DST_ID.
messageId2LE uint16_t per-source transport identifier.
payloadType1Selects inner tail layout — see Payloads.
regionBlock0 or 5Spatial Region block present only if HAS_REGION.
fragment0 or 2Present only if HAS_FRAGMENT.
routeBlockvariablePresent only if ttlRaw & 0x80 (HAS_ROUTE_BLOCK).
Inner tailimplicit lengthappTailLen = rxPhyLen − prefixBytes where prefixBytes is base + region + fragment + route; cipherLen = appTailLen − micLen; on-air **`cipherLen

Exact layouts and bit masks are in Packet layout.

Why this architecture

  • PHY budget honesty: dynamic headers + no payloadLen means implementations derive lengths from the modem rxSize and parsed flags — fewer ambiguous states.
  • Operational simplicity: repeaters do not maintain predictive graphs; scaling is bounded by TTL/hash policies, duplicate caches, and airtime rules.

Important: A LowMesh network does not require a gateway. Gateways are an optional convenience for internet backhaul; off-grid meshes remain valid.

Next steps

LowMeshOS — always open-source mesh protocol documentation