This sample demonstrates how to implement a custom vendor model in Bluetooth Mesh technology. It showcases how to create, implement, and use vendor-specific models for custom data exchange between mesh nodes.
The application implements both a vendor server model and a vendor client model within the same firmware. This allows a single device to both send and receive custom vendor model messages.
The vendor model is defined with:
- Company ID: 0x0059 (Nordic Semiconductor ASA)
- Model IDs:
- Vendor Server Model: 0x1000
- Vendor Client Model: 0x1001
The sample implements four message types:
-
Vendor_SET (Opcode: 0x10 + Company ID)
- Sent from client to server
- STATUS response is expected to be sent by the application
- Acknowledged message type
Field Name Size (octets) Description Opcode 3 0x10 + Company ID (Little Endian) Data 0–377 Arbitrary data payload -
Vendor_Set_Unack (Opcode: 0x11 + Company ID)
- Sent from client to server
- No STATUS response is sent by the application
- Unacknowledged message type (send and forget)
Field Name Size (octets) Description Opcode 3 0x11 + Company ID (Little Endian) Data 0–377 Arbitrary data payload -
Vendor_GET (Opcode: 0x12 + Company ID)
- Sent from client to server
- Supports an optional
length
parameter - If the
length
parameter is provided, the server will limit the STATUS response payload to the specified number of bytes - If not provided, the server sends the full response
- Requires acknowledgment with a Vendor_STATUS response
Field Name Size (octets) Description Opcode 3 0x12 + Company ID (Little Endian) Length 2 (optional) Optional. Number of bytes requested in reply. -
Vendor_STATUS (Opcode: 0x13 + Company ID)
- Sent from server to client
- Sent in response to GET or SET messages
- Automatically sent by the server when the handler returns success (0)
Field Name Size (octets) Description Opcode 3 0x13 + Company ID (Little Endian) Data 0–377 Response data payload
- Two nRF52 or nRF53 series development boards (e.g., nRF52840 DK, nRF5340 DK)
- Smartphone with nRF Mesh mobile app (for provisioning)
-
Clone the nRF Connect SDK and set up your development environment
-
Build the application for your target board (e.g., nRF52840 DK):
west build -b nrf52840dk/nrf52840
-
Flash the application to two development boards:
west flash --erase
- Build and flash the firmware to two development kits.
- Provision both devices using the nRF Mesh mobile app:
- Scan for unprovisioned devices and provision them one by one
- Add them to the same network
- Configure publish/subscribe addresses to establish communication between the devices
- Press Button 1 on one of the devices to send a "Hello World" message using Vendor_Set message (acknowledged)
- Press Button 2 on one of the devices to send a "Hello World" message using Vendor_Set_Unack message (unacknowledged)
- Press Button 3 on one of the devices to send a Vendor_Get request message (no parameters, full response)
- Press Button 4 on one of the devices to send a Vendor_Get request message with the optional
length
parameter set to 1 (response will be truncated to 1 byte) - Observe the message exchange in the console logs
On the device that receives the SET message, you should see:
[00:00:06.156,066] <dbg> vnd_srv: handle_set: Received SET message, data length 301
[00:00:06.156,250] <inf> model_handler: Received SET message: "Hello World- 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
[00:00:06.156,311] <dbg> vnd_srv: bt_mesh_vendor_srv_status_send: Sending STATUS message, data length 301
On the device that sends the SET message, you should see:
[00:00:05.774,597] <inf> model_handler: Sending SET message: "Hello World- 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
[00:00:05.774,658] <dbg> vnd_cli: bt_mesh_vendor_cli_set: Sending SET message, data length 301
[00:00:09.211,883] <dbg> vnd_cli: handle_status: Received STATUS message, data length 301
[00:00:09.212,066] <inf> model_handler: Received STATUS response: "Response OK- 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
The sample consists of the following components:
-
Vendor Model Definitions
include/vnd_common.h
- Common definitions shared by client and serverinclude/vnd_srv.h
- Vendor server model API and context definitionsinclude/vnd_cli.h
- Vendor client model API and context definitions
-
Vendor Model Implementations
src/vnd_srv.c
- Vendor server model implementationsrc/vnd_cli.c
- Vendor client model implementation
-
Application Logic
src/model_handler.c
- Model instance initialization and message handlingsrc/main.c
- Main application, mesh initialization, and button handling
The vendor server model supports asynchronous responses:
-
The server model's callback handlers (
set
andget
) return an integer value:- Return 0 to send the response immediately
- Return non-zero to delay the response (to be sent later)
-
When delaying a response, the application can call
bt_mesh_vendor_srv_status_send()
later when the response is ready. Make sure to save thectx
so that response can be sent to the correct destination. -
This allows for scenarios where response data isn't immediately available, such as:
- Hardware operations that take time to complete
- Communication with other subsystems
- Operations that require user input