Bluetooth Mesh development in c — Friendship Feature

Bluetooth Mesh development in c — Friendship Feature
How Low Power Nodes survive in a mesh network without draining their battery
📡
LPN
Low Power Node
🤝
Friend Node
Message Buffer
📬
Friend Queue
Offline Storage
⏱️
PollTimeout
Keepalive Timer

What is the Friendship Feature?

Imagine you have a battery-powered door sensor in a Bluetooth Mesh network. It cannot afford to keep its radio on all the time — that would drain the battery within days. But other nodes in the mesh might keep sending messages meant for it while it is sleeping.

The Friendship feature solves this problem. A nearby always-on node (called a Friend Node) acts like a postman — it collects and holds messages on behalf of the sleeping sensor. When the sensor wakes up, it asks the friend: “Got anything for me?” and the friend hands over all the buffered messages.

The sleeping sensor is called a Low Power Node (LPN). The always-on helper is the Friend Node. Together they form a Friendship.

Key Terms to Know

Low Power Node (LPN) Friend Node Friend Request Friend Offer Friend Poll Friend Update Friend Queue Friend Subscription List PollTimeout ReceiveDelay ReceiveWindow FSN (Friend Sequence Number) Friend Clear Friend Clear Confirm

Step 1 — How Friendship is Established
Friend Request Friend Offer Friend Poll Friend Update

When an LPN wants a friend, it broadcasts a Friend Request message to the whole mesh. Any nearby Friend-capable node hears this and can reply with a Friend Offer.

Multiple Friend nodes may reply — the LPN picks the best one (based on signal strength and receive window size) and sends a Friend Poll directly to that chosen node. The Friend node responds with a Friend Update, and the friendship is now officially established.

Friendship Establishment Flow:

LPN Friend 1 Friend 2 Friend 3
Needs Friend
──Friend Request──▶ ──▶ ──▶ ──▶
Each Friend calculates delay = f(RSSI, ReceiveWindow)
◀──Friend Offer── ◀──
◀──Friend Offer── ◀──
◀──Friend Offer── ◀──
Chooses Friend 2
──Friend Poll──▶ ──▶
◀──Friend Update── ◀──
No Friendship ✅ Friendship Established No Friendship

Once friendship is established, the Friend node creates an empty Friend Subscription List and starts storing incoming messages for the LPN in the Friend Queue.

Step 2 — How the LPN Collects Its Messages
Friend Poll FSN Friend Queue ReceiveDelay / ReceiveWindow

The LPN wakes up periodically and sends a Friend Poll message to ask: “Do you have anything for me?” The Friend node replies with the oldest message in the queue.

The LPN uses a Friend Sequence Number (FSN) bit in the Poll message to confirm receipt. If the FSN value is the same as the previous Poll, it means the LPN didn’t get the last message — the Friend re-sends it. If the FSN changes, the Friend knows the LPN got it and sends the next message.

FSN Logic — What the Friend Does:

Poll FSN Friend Action Why
Same as last Poll Re-send the same message (if not discarded) LPN did not acknowledge previous delivery
Different from last Poll Send next (oldest) message from queue LPN confirmed receipt of previous message

The Friend must reply within a window: ReceiveDelay ≤ reply time ≤ (ReceiveDelay + ReceiveWindow). This gives the LPN a predictable wakeup window — it can go to sleep right after the window closes.

Response Timing Window:

LPN sends
Friend Poll
ReceiveDelay
(min wait)
✅ Valid window
Friend replies here
❌ Too late
(after ReceiveDelay + ReceiveWindow)
e.g. 100ms 100ms → 350ms > 350ms

Important note: Messages in the Friend Queue are sent unchanged — even if the IV Index (network security index) has changed on the Friend node. The LPN must poll at least once every 96 hours, or the Friend may discard queued messages.

Step 3 — When Does Friendship End?
PollTimeout Friend Queue discard Friend Clear

A friendship has a PollTimeout timer on the Friend node side. Every time the Friend receives a Friend Poll, a Friend Subscription List Add, or a Friend Subscription List Remove message from the LPN, the timer resets.

If the LPN goes silent — doesn’t send any of those messages — and the PollTimeout timer expires, the Friend node:

  • Terminates the friendship
  • Discards everything in the Friend Queue

Friendship Termination by PollTimeout:

LPN Friend Node
Friendship Established Friendship Established + PollTimeout starts
──Friend Poll──▶ ◀── Friend Update (PollTimeout resets)
LPN goes silent / offline ⏳ PollTimeout counting down…
── Poll ──✕ (no reply) No message received
── Poll ──✕ (no reply) No message received
Friendship Terminated (LPN side) ⌛ PollTimeout expired → Queue discarded

The Friend also terminates the friendship immediately if it receives a Friend Clear message — this happens when the LPN has moved on and found a new Friend (see next section).

Step 4 — The Friend Clear Procedure (Switching Friends)
Friend Clear Friend Clear Confirm Exponential Backoff PreviousAddress

When an LPN drops its old Friend and establishes a friendship with a new one, the new Friend must notify the old Friend to clean up. This is done using a Friend Clear message.

The new Friend knows about the previous Friend because the LPN includes the old Friend’s address in the PreviousAddress field of the Friend Request message.

Friend Clear Procedure — Step by Step:

Step What Happens
1 New Friend sends Friend Clear to old Friend’s address with TTL set to maximum
2 Two timers start: Friend Clear Repeat (1 second) and Friend Clear Procedure (2 × PollTimeout)
3 If old Friend replies with Friend Clear Confirm → both timers cancelled, procedure done ✅
4 If Repeat timer expires with no reply → send another Friend Clear, double the Repeat timer (1s → 2s → 4s → …)
5 If Procedure timer (2 × PollTimeout) expires → cancel Repeat timer, give up, procedure done ✅

Friend Clear Retry with Exponential Backoff:

New Friend Node Old Friend Node Timer
── Friend Clear ──▶ (offline / no reply) 0s — start
── Friend Clear ──▶ (offline / no reply) 1s expired
── Friend Clear ──▶ ◀── Friend Clear Confirm 2s expired
✅ Procedure Complete — Old friendship cleared

Step 5 — Friend Subscription List (Group Messages)
Subscription List Add Subscription List Remove Subscription List Confirm

By default, the Friend only stores messages addressed directly to the LPN’s unicast address. But what if the LPN also wants messages sent to a group address (like “all lights” or “all sensors”)?

The LPN sends a Friend Subscription List Add message telling the Friend: “Also buffer messages sent to these group addresses for me.” The Friend adds them to the Friend Subscription List and replies with a Friend Subscription List Confirm.

Similarly, the LPN can send Friend Subscription List Remove to stop buffering messages for a particular group address.

Subscription List Update Flow:

LPN Friend Node
── Subscription List Add [0xC001] ──▶ Adds 0xC001 to Subscription List
◀── Subscription List Confirm ── Sent within ReceiveDelay + ReceiveWindow
── Subscription List Remove [0xC001] ──▶ Removes 0xC001 from Subscription List
◀── Subscription List Confirm ── TransactionNumber matches request

BlueZ — Working with Mesh Friendship
bluetoothctl mesh mesh-cfgclient D-Bus API

BlueZ supports Bluetooth Mesh via the bluetooth-meshd daemon. You interact with it through D-Bus or the bluetoothctl / mesh-cfgclient tools. Below are practical examples.

1. Check if mesh daemon is running:

sudo systemctl status bluetooth-meshd

# Start it if not running
sudo systemctl start bluetooth-meshd
sudo systemctl enable bluetooth-meshd

2. Join a mesh network and provision a node:

# Start mesh-cfgclient (BlueZ mesh configuration client)
mesh-cfgclient

# Inside the tool — discover unprovisioned devices
discover-unprovisioned on

# Provision a device (UUID shown in scan results)
provision <device-UUID>

3. Get feature information from a node (including Friend/LPN support):

# Inside mesh-cfgclient — get composition data (includes feature flags)
composition-get <node-unicast-address> 0

# Feature flags in Composition Data Page 0:
# Bit 0 = Relay
# Bit 1 = Proxy
# Bit 2 = Friend       <-- Friend feature supported
# Bit 3 = Low Power    <-- LPN feature supported

4. Enable the Friend feature on a node via config model:

# Set Friend feature ON (1 = enable, 0 = disable)
# Uses Configuration Friend Set message
friend-set <node-unicast-address> 1

# Verify Friend state
friend-get <node-unicast-address>

5. D-Bus — interact with mesh node programmatically (Python example):

import dbus

# Connect to the system bus
bus = dbus.SystemBus()

# Get the mesh management interface
mesh_obj = bus.get_object(
    'org.bluez.mesh',
    '/org/bluez/mesh'
)
manager = dbus.Interface(mesh_obj, 'org.bluez.mesh.Network1')

# Attach to an existing mesh network node
# token is a 64-bit value returned at provisioning time
token = dbus.UInt64(0x1234567890ABCDEF)
manager.Attach('/org/example/mesh_app', token)

6. Monitor Friend/LPN messages using btmon:

# btmon captures all HCI events — mesh PDUs go over HCI as LE advertising
sudo btmon -w mesh_capture.btsnoop

# In another terminal, run your mesh application
# Then open the .btsnoop file in Wireshark for full mesh dissection

# Alternatively, filter mesh ADV packets live:
sudo btmon | grep -A5 "ADV_NONCONN_IND"

7. Check PollTimeout value on a Friend node (Config model):

# LPN Poll Timeout Get — asks Friend what timeout is configured for a given LPN
# inside mesh-cfgclient:
lpn-poll-timeout-get <friend-node-address> <lpn-unicast-address>

# Expected response includes PollTimeout in 100ms units
# e.g. value 0x000320 = 800 units × 100ms = 80 seconds

Quick Reference — All Friendship Messages
Message Sender Purpose
Friend Request LPN Broadcast — “I am looking for a Friend”
Friend Offer Friend Node “I can be your Friend — here are my parameters”
Friend Poll LPN “Do you have messages for me?” (also resets PollTimeout)
Friend Update Friend Node Delivers a queued message (or confirms queue is empty)
Friend Clear New Friend Node “LPN has moved to me — please terminate your friendship”
Friend Clear Confirm Old Friend Node “Acknowledged — I have terminated the friendship”
Subscription List Add LPN Add group addresses to buffer on Friend side
Subscription List Remove LPN Remove group addresses from Friend’s buffer list
Subscription List Confirm Friend Node Confirms Add or Remove was applied

Keep Learning Bluetooth Mesh

Explore more protocol layers on EmbeddedPathashala — free tutorials for engineers.

Leave a Reply

Your email address will not be published. Required fields are marked *