Skip to content

Architecture

spec v0.5.0

Terminology: this document uses the canonical terms defined in project/glossary.md. When unsure (node vs trap, network vs region, K_group vs K_admin), defer there.

meshtrap is federated. The central service is shared infrastructure that anyone can self-host; networks below it are sovereign trust domains.

Central service (a SaaS aggregator — public default or self-hosted)
└─ Org (the billing / ownership unit; e.g. DOC)
└─ Network (one LoRa trust domain: one K_admin, one K_group)
└─ Region (one hub manages this geographic subdivision)
└─ Cluster (one router + its child traps)
└─ Trap
  • A central service hosts many orgs.
  • An org may own many networks (e.g. DOC’s per-park networks).
  • A network may have many regions; each region has exactly one hub.
  • A region’s hub manages many clusters; each cluster has one router and its children.

Networks never share LoRa traffic — different keys, different sync words, different airwaves in effect. Federation happens at the central service layer via telemetry, not on the radio.

The system uses four firmware roles. All field roles share a single firmware binary; the role is selected at provisioning time via a configuration flag.

RoleHardware familyPower sourceRX policyPrivileged commands
ENDPOINTnRF52840 + SX1262Tiny solar + small batt1 s window after each TXNo
ROUTERnRF52840 + SX1262Larger solar + battAlways-onNo
HUBESP32-S3 + SX1262Mains / large batteryAlways-onYes (with K_admin)
TECHnRF52840 + SX1262 + UIRechargeableAlways-on while in useYes (with K_admin)

Hardware SKUs differ in physical packaging (enclosure, panel size, battery capacity), not silicon. The same PCB design serves both ENDPOINT and ROUTER roles; only the enclosure changes.

A two-tier hierarchy:

┌─────────┐
│ Hub │
└────┬────┘
│ LoRa
┌────────────────┼────────────────┐
│ │ │
┌───┴───┐ ┌───┴───┐ ┌───┴───┐
│ R1 │◄──────►│ R2 │◄──────►│ R3 │ Router tier
└───┬───┘ └───┬───┘ └───┬───┘ (dynamic routing)
│ │ │
┌───────┼───────┐ ┌───┴───┐ ┌───┴───┐
│ │ │ │ │ │ │
E1 E2 E3 E4 E5 E6 E7 Endpoint tier
(static parent)
  • Each endpoint has a router preference list of up to N router IDs (default 4, minimum 1, maximum 8), set at deployment and updatable remotely. The first router in the list is the current primary; the rest are fallbacks in order.
  • Endpoints never multi-hop. They talk only to routers in their preference list.
  • Endpoints are TX-driven (one short RX window after each TX; extended to 30 s when the router sets config_pending).
  • If missed_ack_count exceeds a threshold against the current primary, the endpoint falls down its preference list one router at a time, emitting HELP frames if every entry fails.
  • A preference list of length 1 is accepted but flagged by the wizard as a single point of failure; a list of length 2 is acceptable without warning. Default (4) provides graceful degradation as the network evolves.

Ordering of the preference list is hub-curated by default:

  • Endpoints report signal quality (last_ack_rssi, last_ack_snr) in each STATUS. The hub assembles a per-link quality matrix across the network.
  • When network topology changes (a router added, removed, or its signal to a child degrades), the hub queues COMMANDs that reorder, add to, or trim each affected endpoint’s preference list.
  • When a new router is registered with a GPS location, the hub identifies traps within an expected coverage radius and appends the new router to their preference lists at the bottom. Promotion up the list happens after the endpoint has reported good signal to it.

An autonomous-reorder toggle exists per-network (default off): when enabled, endpoints reorder their own preference list based on observed signal, with a self-recovery rule — if reordering leaves the endpoint unable to reach any router, it reverts to the last hub-pushed order. Off by default because hub-side ordering has full visibility and avoids sleep-current penalties on the endpoint.

  • Routers exchange routing beacons among themselves (distance-vector, see below).
  • Each router selects a parent toward the hub based on hop count and link cost.
  • Routers are RX-always-on, so they can receive endpoint traffic at any time and forward toward the hub.
  • A router is also a trap node — its own reed switch / status is reported in the same way as an endpoint, alongside its routing duties.
  • The hub is the deployment’s authoritative state. It holds the canonical map of nodes, locations, last-seen timestamps, and health.
  • The hub serves a local web UI over Wi-Fi for management and history.
  • The hub optionally forwards telemetry to a central server over MQTT. The central server is out of scope for v1.

The hub is defined by firmware role, not by a specific hardware product. Any ESP32-S3 + SX1262 board can be a hub. Specifically:

  • SenseCAP Indicator hub: SenseCAP Indicator (ESP32-S3 + SX1262 + 480×480 touchscreen + RP2040 sensors). The hub firmware drives the display as a status dashboard and uses the touchscreen for at-a-glance ops.
  • Headless hub: any ESP32-S3 + SX1262 board (XIAO, Heltec, custom PCB) with no display. Identical firmware minus the display layer; managed entirely via the LAN web UI.
  • Display-optional hub: a hub board with a smaller display (e.g. OLED) gets a cut-down dashboard showing alert counts and the hub’s LAN IP.

The display is a UX layer, not a functional requirement. A hub without a display still serves the full web UI and MQTT relay.

  • Functionally a mobile router with a UI and privileged-command access.
  • Can act as a router (issue JOIN_ACKs, push commands) when out of hub range.
  • Authenticates privileged commands with K_field (a key separate from K_admin — decision pending; see D-02). Until that split lands, tech nodes carry K_admin and inherit the same blast radius as a hub.
  • Aggregates telemetry from hubs over MQTT.
  • Holds RBAC, registration, deployment metadata, and the public registration / dashboard surface.
  • Never holds K_admin. K_admin is generated at the hub on first setup and never transmitted to the central service. A central-service compromise can leak K_group and rosters, but cannot mint commands.
  • Optional. Hubs can run standalone (no central service) or with a self-hosted instance or with the project’s default public instance.

See server/ for the central-service tech stack and RBAC model.

A small distance-vector protocol, run only among routers:

  • Each router periodically broadcasts a ROUTING_BEACON frame containing {my_id, hops_to_hub, link_cost_to_parent, seq}.
  • Beacon interval: 30–60 minutes (configurable, deployment-dependent).
  • The hub beacons hops_to_hub = 0.
  • Each router selects as parent the neighbour minimising (hops_to_hub + 1) + link_cost, tie-broken by RSSI.
  • Split-horizon: a router does not advertise a route back through its own parent.
  • Forwarded uplinks carry a small TTL to bound loops in pathological cases.

This is small enough (~30 lines of logic) to maintain without a routing library. Routers are stationary, the graph is small (≤15 routers per deployment in expected scenarios), and update intervals are long.

┌──────────────────────────────────────────────────────────────┐
│ Application │
│ - Trap status, battery, commands, JOIN sequence │
├──────────────────────────────────────────────────────────────┤
│ Routing │
│ - Endpoint→parent (static), Router→hub (distance-vector) │
├──────────────────────────────────────────────────────────────┤
│ Security │
│ - AES-128-CCM, K_group encryption, K_admin signing, │
│ seq-based replay protection │
├──────────────────────────────────────────────────────────────┤
│ MAC │
│ - Frame framing, ACK-requested bit, retry/dedup, │
│ randomised backoff │
├──────────────────────────────────────────────────────────────┤
│ PHY │
│ - SX1262, 864–868 MHz, SF9/125 kHz/+14 dBm default │
└──────────────────────────────────────────────────────────────┘
  • MVP (Phases 1–6): one network, one hub, one operator, hardcoded keys until provisioning lands, no central service, no multi-tenancy.
  • v1.0 (Phases 7–8b): central service with single-org / single-network support, basic RBAC, MQTT relay, Trap.NZ push (one-way), headless hub.
  • v1.5: multi-tenant central service, multi-network per org, public role, web flasher, Trap.NZ bidirectional, registration flow with operator-approved enrolment, SNR-based router-list suggestions.
  • v2.0+: OIDC for orgs, autonomous endpoint reordering, optional AI-assisted optimisation, OTA K_admin rotation (Option B or C; see D-02).

See roadmap.md for the phased plan.

  • Central service (lands at v1.0 in Phase 7–8b).
  • Cellular hub variant.
  • Pairwise per-node keys (group key only).
  • OTA firmware updates over LoRa.
  • OTA K_admin rotation.