Appearance
Protocol overview
Status: LowMesh has not been publicly released. This repository documents the current LowMesh mesh specification:
verFlagsVERSION bits 15–14 =0b10identify the current header layout (not a public API v1/v2 release), a dynamic 16-byte minimum base header (20 bytes withHAS_DST_ID), mandatory on-wiresessionId(4 bytes LE at offset0x09), 16-bitchannelHashandmessageId, 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
| Layer | Responsibility |
|---|---|
| PHY / MAC | Channel access, preamble, LoRa CRC16 (modem), optional whitening — see Packet layout. |
| Link | Neighbor discovery, link metrics, optional time sync slots. |
| Network | Hop 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. |
| Transport | messageId (16-bit), optional fragment block, ACK / FRAG_NACK — see Fragmentation. |
| Application | payloadType selects the inner body: TEXT_UTF8 / POSITION_CORE / TELEMETRY_BASIC, PAYLOAD_BODY_V2, admin (0x91/0x92), etc. — see Payloads. |
Design principles
- Explicit roles — Primary roles are Client, Repeater, and Gateway. Profiles (e.g. Standard Client, Sensor) describe behavior within a role.
- 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.
- Channel policy — The header carries
channelHash(LEuint16_t, truncated from the normative digest — see Channels & security).channelHash == 0x0000is the default community domain: AES-256-CCM-4 with ROMdefaultCommunityPsk32(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. - 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.
| Field | Size | Description |
|---|---|---|
verFlags | 2 | Version (15–14), optional blocks, FLOOD, HASH_SIZE, etc. — see Packet layout. |
channelHash | 2 | LE uint16_t — see Channels & security. 0x0000 = default community (ROM defaultCommunityPsk32, still CCM-4). |
hopControl (ttlRaw) | 1 | Hop / relay semantics — see Routing. |
srcId | 4 | Source nodeId32. |
sessionId | 4 | Mandatory transport session (LE uint32 at offset 0x09). Persisted in NVM; used in CCM nonce and duplicate/replay keys — see Channels & security. |
dstId | 0 or 4 | Present only if HAS_DST_ID. |
messageId | 2 | LE uint16_t per-source transport identifier. |
payloadType | 1 | Selects inner tail layout — see Payloads. |
regionBlock | 0 or 5 | Spatial Region block present only if HAS_REGION. |
fragment | 0 or 2 | Present only if HAS_FRAGMENT. |
routeBlock | variable | Present only if ttlRaw & 0x80 (HAS_ROUTE_BLOCK). |
| Inner tail | implicit length | appTailLen = 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
payloadLenmeans implementations derive lengths from the modemrxSizeand 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
- Device roles and profiles — Roles, Standard/Sensor profiles, Dynamic Repeater Mode.
- Base interoperability profile — Minimum compatible defaults.
- Compatibility matrix — Base Profile vs optional vs design-target features.
- Golden test vectors — Placeholder vectors until reference firmware emits final golden hex.
- Routing — Flood, strict source route on wire, TTL ceilings, duplicate suppression.
- Routing on wire — Routing block vs encrypted inner tail.
- Payloads —
payloadTypedispatch: core types,PAYLOAD_BODY_V2. - Node identity & advertisement — Long/short names,
NODE_ADVERT, optional GPS, peer tables. - Contacts, presence & away message — Local contact rows, NVM away text,
AWAY_MSG_REQ/AWAY_MSG_RSP. - Traceroute & link metrics — RSSI, SNR, per-hop link budget.
- Embedded storage (C++) — NVM structs;
ParsedBaseHeader+ modular parsers (no rigid singleMeshHeaderstruct). - Mesh admin & operator channel — Remote bulletin/config;
ADMIN_CMD/ADMIN_RSP,BATCH_EXECUTE. - IoT: hop budget & ACK downlinks — Sensor Profile; Gateway-targeted uplink and ACK windows.
- ATAK / TAK compatibility — Client + companion CoT path,
GPS_FIX→ track mapping, UID conventions.