Please enable JavaScript to view this website.

Skip to main content
Experimental proof of concept

Edge Mesh is a throwaway proof-of-concept / learning experiment built on top of the Greengrass reference implementation. It is not a supported or maintained deliverable and may be removed. The reference implementation itself is long-lived; Edge Mesh is not.

Data Path

In a nutshell

The mesh carries three flows, all over the same isolated 10.88.0.0/24 links with only the core reaching AWS: (1) a Pi scans BLE tools, builds an MQTT message payload, and publishes to the core's broker, which relays to the cloud; (2) a Pi provisions its AWS IoT cert through the core's broker; (3) a remote software client drives a ONE-KEY tool by relaying opaque OpenLink packets through the core to whichever Pi is in range.

Read this if: you're a software engineer following the actual message flows.

Before this: skim the Overview.

This page is for software engineers. It traces the three flows the mesh carries: the BLE-scan-to-cloud pipeline, client-device (Pi) provisioning relayed through the core, and EdgeMesh Bluetooth tool control. All three ride the same isolated 10.88.0.0/24 mesh; only the core has the cellular link out.

BLE scan → mesh MQTT → cloud

A Pi mesh-node scans nearby Milwaukee tool advertisements and forwards each session to the core, which relays it to AWS IoT Core.

Key points:

  • The Pi scans with bleak, keeps only Milwaukee adverts (company id 0x0165), reconstructs the xAd via edge_shared.ble.build_xad, and dedups within a session.
  • edge_shared.payload.build_payload(thing, session, mesh_mac=…) produces the RP2 payload (schema version 2). The Pi passes its batman originator MAC as meshMac so the core's map places detected tools on the detecting node, not the core.
  • The payload publishes to dt/<thing>/asset_scan on the core's Moquette broker over the mesh; the core's Bridge relays it to $aws/rules/dt_asset_scan_ingest/... (Basic Ingest) over cellular. The Pi never opens a direct AWS connection.
  • Scan cadence (enabled, ble_scan.duration_sec, ble_scan.rssi_threshold, ble_scan.schedule) comes from the per-Pi config named shadow, reconciled on connect and hot-updated via delta, relayed end-to-end through the core's Bridge, so the Pi reconfigures without a restart.

The core also runs its own ble-scanner + asset-publisher for its local range; the mesh Pis extend coverage into areas the core can't hear.

Client-device provisioning relay

A mesh Pi is an AWS IoT client device, not a Greengrass core. It obtains its operational certificate over the mesh, relayed through the core, never touching the internet directly. This reuses the platform's two-phase certificate model but runs Phase 2 against the core's broker.

Key points:

  • The bootstrap cert is minted per-Pi via the Milwaukee cert API at provisioning time (on the operator's Mac, tools/provision-pi.sh + tools/mint_bootstrap_cert.py). The bootstrap private key is generated on the Pi and never leaves it.
  • Each Pi maps to one IoT thing named by its MPBID (mesh-Pi MPBIDs begin with FFFC). CDA authorizes it via the thingName: FFFC* selection rule; per-thing isolation keeps one Pi from acting as another.
  • Phase 2 (fleet-provisioning-by-CSR) runs against the core's Moquette broker, and the Bridge relays the reserved $aws/certificates/* and $aws/provisioning-templates/* topics to AWS IoT Core. edge_shared.provision.provision_by_csr is endpoint-agnostic, so the same code the core's cert-manager uses against AWS is what the Pi uses against Moquette.
  • Serialize first boots: the core handles provisioning requests one at a time, so bring up one Pi at a time on first boot.

EdgeMesh Bluetooth control flow

An operator drives a ONE-KEY tool from a remote software client even though the software client and tool are never in Bluetooth range of each other. The core registers as a WebSocket host gateway and relays opaque OpenLink bytes over the mesh to whichever Pi is in range of the tool.

Key points:

  • No AWS IoT Core / MQTT-shadow in the control path. The gateway's only cloud link is the outbound control-gateway-websocket WebSocket; everything else is local pub/sub and mesh MQTT. The mesh remains an isolated side-channel.
  • The gateway registers with hostUUID = AWS_IOT_THING_NAME, the core's own MPBID, so a browser addresses it directly by MPBID with no gatewayCode handshake.
  • Mesh topics for a target Pi with thing name {mpbid}:
    • edgemesh/{mpbid}/cmd: gateway → Pi (open / cmd / close)
    • edgemesh/{mpbid}/resp: Pi → gateway (a tool GATT notification, relayed verbatim)
    • edgemesh/{mpbid}/evt: Pi → gateway (connected + MTU, disconnect, connect-failed, write-failed)
  • The gateway is a byte pipe with session bookkeeping (SessionRouter). It never interprets or decrypts OpenLink payloads. The only transformation is hex ⇄ base64 transcoding at the browser/mesh boundary (the browser speaks hex, the mesh speaks base64). The encrypted OpenLink handshake runs end-to-end between the browser and the tool.
  • On the Pi, relay.py is a library that runs inside publisher.py (not a separate service), because CDA ties the MQTT client id to the thing name: one Pi, one connection, shared by scanning and relay. The relay maps a command kind to a GATT characteristic on the tool's OpenLink service and shares the single BLE radio with the scanner via a lock.

Where the code lives