Bluetooth Mesh Networking

IoTEmbeddedArchitecturePerformance
Share on LinkedIn

A warehouse needs 500 occupancy sensors to control lighting across 40,000 square meters. Wi-Fi APs every 15 meters is expensive. LoRaWAN is one-directional. Bluetooth Mesh puts a $3 BLE chip in every light fixture and sensor, and messages hop relay-to-relay until they reach the target. No infrastructure beyond the nodes themselves. It's not fast (messages take 10-50ms per hop) and it's not for streaming data. It's for "turn on group 7" and "occupancy detected in zone B3" — commands and state, not payloads.

Mesh topology

Provisioner (phone/gateway)
    │
    ▼
┌─────────┐    relay    ┌─────────┐    relay    ┌─────────┐
│ Sensor  │ ──────────► │ Light 1 │ ──────────► │ Light 2 │
│ (LPN)   │             │ (relay) │             │ (relay) │
└────┬────┘             └─────────┘             └─────────┘
     │ friend
     ▼
┌─────────┐
│ Friend  │
│ node    │
└─────────┘

Provisioning

Nodes join the mesh through a provisioning process:

// Provisioner side (nRF Connect SDK)
static void prov_complete(uint16_t net_idx, uint16_t addr) {
    LOG_INF("Node provisioned: addr 0x%04x on net_idx %u", addr, net_idx);

    // Configure: add to groups, set publish/subscribe addresses
    cfg_cli_mod_app_bind(net_idx, addr, 0, 0, 0);  // bind Generic OnOff to AppKey
    cfg_cli_sub_add(net_idx, addr, 0, GROUP_ADDR_LIGHTS_ZONE_B);
}

// Unprovisioned device advertises with UUID
// Provisioner scans, selects device, exchanges public keys (ECDH P-256)
// Device receives: NetKey, AppKey, unicast address

After provisioning, the node is part of the mesh with a unique unicast address and shared network key.

Models: the application layer

Mesh models define message types:

Model Messages Use
Generic OnOff OnOffSet, OnOffStatus Simple on/off control
Generic Level LevelSet, LevelStatus Dimming (0-65535)
Light Lightness LightLightnessSet Light output level
Sensor SensorStatus Sensor data reporting
Generic Location LocationGlobalSet Asset position

Models use publish/subscribe addressing:

// Sensor publishes occupancy to group 0xC001
struct bt_mesh_model_pub pub = {
    .addr = 0xC001,  // group address
    .period = MSEC_PER_SEC * 5,
};

// Light subscribes to group 0xC001 — turns on when occupancy published
struct bt_mesh_elem elements[] = {
    BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, onoff_cli_ops, &pub, NULL),
};

One sensor publish turns on every light subscribed to that group. No central controller needed.

Message flow and relay

Messages flood through the network with controlled relay:

Sensor (addr 0x0005) publishes to group 0xC001
    → Light relay (0x0010) receives, retransmits (TTL-1)
    → Light relay (0x0015) receives, retransmits (TTL-1)
    → Light target (0x0020) receives, executes OnOffSet

TTL (Time To Live) limits hop count — typically 5-7 hops. Each relay decrements TTL. Network-wide messages use managed flooding with cache to prevent infinite loops.

Friend and Low Power Node

Battery sensors can't listen constantly. The friendship protocol solves this:

LPN (sensor):  sleep ──wake──poll friend──sleep──wake──poll friend──sleep
Friend (light):  always listening, stores messages for LPN
// LPN configuration
struct bt_mesh_lpn {
    .pollTimeout = 300,   // poll every 300 * 100ms = 30 seconds
    .pollIntvl = 10,      // poll interval steps
    .retryIntvl = 10,
};

// Friend automatically established with nearest relay node
bt_mesh_lpn_set(true);

LPN battery life: 1-3 years on coin cell with 30-second poll interval, depending on message frequency.

Network sizing guidelines

Parameter Recommendation
Nodes per network Up to 32,000 (spec limit), practical 500-2,000
Relay nodes Every 5-10 meters in indoor environments
Groups Organize by zone/function (max 16,384 group addresses)
Subnets Separate subnets for security zones (max 4,096 subnets)
Provisioner One active provisioner; backup provisioner recommended

nRF Connect SDK example

Nordic's SDK provides mesh samples:

# Build mesh light client
west build -b nrf52840dk_nrf52840 samples/bluetooth/mesh/light_lc

# Build mesh sensor server
west build -b nrf52840dk_nrf52840 samples/bluetooth/mesh/sensor_server

Flash provisioner on a DK, provision sensor and light nodes via nRF Mesh mobile app, then test group control.

Provision mesh networks with a known-good topology before scaling to 100+ nodes — reactive routing under load differs from lab mesh of five devices.

Security and provisioning

Mesh provisioning is the attack surface:

Provisioner → Provisioning bearer → Device joins network
Network key distributed encrypted during provisioning

Use Out-of-Band (OOB) authentication when possible — numeric comparison or QR code, not just "accept any provisioner." Rotate network keys on device RMA or security incident.

Message relay and hop limits

Default TTL is 5 hops — messages die after 5 relay nodes:

Node A → Relay B → Relay C → Relay D → Relay E → Node F (delivered)
Node A → ... → 6th hop (dropped)

Design topology so any node reaches gateway within 4 hops. Add relay nodes rather than increasing TTL — higher TTL increases network congestion exponentially.

Coexistence with BLE connections

Mesh and BLE GATT can coexist on same chip but share radio time:

Pair with Android BLE bluetooth low energy for phone-to-mesh gateway applications.

Common production mistakes

Teams get mesh networking bluetooth wrong in predictable ways:

IoT deployments of mesh networking bluetooth fail in the field when firmware assumes stable Wi-Fi, OTA rollback is untested, and device certificates expire without automated renewal.

Resources

Frequently asked questions

What is Bluetooth Mesh?

Bluetooth Mesh is a flooding-based mesh networking protocol built on BLE advertising. Nodes relay messages to extend range beyond a single radio hop. It supports thousands of nodes in a network with publish/subscribe messaging, making it suitable for commercial lighting, sensing, and asset tracking where Wi-Fi coverage is impractical.

How is Bluetooth Mesh different from BLE point-to-point?

Standard BLE is one-to-one (central connects to peripheral). Bluetooth Mesh has no central — every node can relay messages. Devices publish to group addresses and subscribers receive regardless of which relay path delivered the message. Range extends through relay nodes, not higher transmit power.

What are relay and friend nodes in Bluetooth Mesh?

Relay nodes retransmit messages to extend network range — typically mains-powered lights or dedicated routers. Friend nodes store messages for Low Power Nodes (LPNs) that sleep most of the time — the LPN polls its friend for pending messages. This lets battery sensors participate in a mesh without staying awake constantly.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →