Bluetooth Low Energy Mesh Network (BLE Mesh)
Bluetooth Low Energy Mesh Network (BLE Mesh) is a communication protocol built on top of the Bluetooth Low Energy (BLE) protocol. It allows a large number of BLE devices to form a mesh network, enabling interconnection and coordinated control between devices over a sufficiently large physical coverage area, thereby meeting the communication needs of multi-device scenarios.
The BLE Mesh communication protocol supports excellent characteristics such as low power consumption, scalability, flexibility, high reliability, and security. It has broad application value in fields such as smart homes, smart lighting, industrial automation, healthcare, and environmental monitoring.
1. Basic Concepts
BLE Mesh Network
A BLE Mesh network is a many-to-many network topology in which device nodes in the network send and receive messages through a "publish / subscribe mechanism".
Device Provisioning
An unprovisioned BLE Mesh device needs to complete the provisioning operation before it can join the BLE Mesh network and become a device node, communicating with other nodes in the network via messages. The device that helps a BLE Mesh device complete the provisioning operation is called the "Provisioner".
Device Node
An unprovisioned BLE Mesh device, after the provisioning operation, becomes a device node in the BLE Mesh network. A device node generally has one or more of the relay, proxy, friend, and low-power characteristics.
A device node is composed of multiple elements, each element contains multiple models, and each model defines the basic functions of the node, such as the states required by the node, the messages that control the states, and the actions produced by processing the messages. The implementation of node functions is based on models. Models can be divided into SIG models and custom models, the former defined by SIG and the latter defined by developers. Models can also be divided into client models and server models based on the sender / receiver of messages.
Mesh Address
For device nodes in a BLE Mesh network to communicate with each other via messages, each node needs to be assigned an address for sending and receiving messages. Mesh addresses are mainly divided into three types: unicast addresses, group addresses, and virtual addresses.
A unicast address is assigned by the "Provisioner" after the device is successfully provisioned. A unicast address may appear in the source / destination address field of a message. A message sent to a unicast address can only be processed by the element that owns that unicast address.
A group address is a type of multicast address in a BLE Mesh network, usually used to group device nodes. If a message with a group address is sent, all device nodes that have subscribed to that group address will receive the message.
A virtual address is associated with a specific UUID label and can be used as a model's publish address or subscribe address.
Mesh Message
Mesh messages are divided into control messages and access messages. Control messages are messages related to BLE Mesh network operations, such as heartbeat and friend request messages. Access messages allow a client model to retrieve or set state values in a server model, or be used by a server to report state values.
A Mesh message is the basic unit of data transmission in a BLE Mesh network, consisting of an opcode and carried parameters. The former is used to uniquely identify the purpose of the message, and the latter can store valid data, such as the destination address, device state, etc.
Proxy Device
If you want other devices that are not BLE Mesh devices (such as a phone) to also become a member of the BLE Mesh network, you can establish a GATT connection with a proxy device node and, with the help of the proxy device, send and receive various messages in the BLE Mesh network.
2. Usage Flow of the "BLE Mesh Plugin"
Based on the standard BLE Mesh communication protocol, the basic capabilities of BLE Mesh are provided in the form of a plugin. Developers can implement functions such as local rapid provisioning, control management, and network sharing of BLE Mesh devices through the "BLE Mesh Plugin".
2.1 Integrate the Plugin
Before using the plugin, you first need to add the plugin in the management backend under "Settings - Third-party Services - Plugin Management". Developers can log in to the management backend, find the plugin, and add it. Then declare the specified version of the plugin in the app.json file.
"plugins": {
"ble-mesh-plugin": {
"version": "latest",
"provider": "sud013447465d3aa024"
}
}The relevant APIs of the "BLE Mesh Plugin" can only be obtained through the requirePlugin method. For example, you can call it like the following:
const { getMeshBLEManager } = requirePlugin('ble-mesh-plugin')2.2 Initialize the BLE Mesh Bluetooth Configurator
Before using the BLE Mesh-related capabilities, you need to initialize the BLE Mesh Bluetooth configurator, which is used to scan for and discover surrounding BLE Mesh devices.
const meshBLEManager = getMeshBLEManager()
meshBLEManager.init().then(({ enabled }) => {
if (!enabled) {
sud.showModal({
title: 'Error',
content: 'Bluetooth is not enabled. Please turn on Bluetooth and try again',
showCancel: false,
})
}
})2.3 Scan for and Discover BLE Mesh Devices
After the BLE Mesh Bluetooth configurator is initialized, you need to scan for BLE Mesh devices via meshBLEManager.startScanMeshDevice. If a device is scanned nearby, the meshBLEManager.onMeshDeviceFound event is called back, returning the scanned BLE Mesh device instance. Since scanning for devices is relatively resource-intensive, please call meshBLEManager.stopScanMeshDevice promptly to stop scanning after finding the required device.
meshBLEManager.onMeshDeviceFound((res) => {
// The scanned BLE Mesh device
console.log(res.device)
// After finding the required device, stop the scan operation
meshBLEManager.stopScanMeshDevice()
})
// Start scanning for BLE Mesh devices
meshBLEManager.startScanMeshDevice({
allowDuplicatesKey: false,
})2.4 Create a BLE Mesh Network
To achieve interconnection and coordinated control between multiple BLE Mesh devices, you first need to create a BLE Mesh network.
createMeshNetwork({ name: 'mesh_network' }).then((res) => {
// After creating a BLE Mesh network, a unique network identifier id is generated, used for subsequent network management, device provisioning, device message communication, and other functions.
console.log(res.networkId)
})2.5 Share a BLE Mesh Network
Developers can implement the import and export of BLE Mesh network data through exportMeshNetworks and importMeshNetworks, allowing multiple users to control and manage the BLE Mesh devices under the same network. In addition, calling getMeshNetworks can also obtain the list of all currently existing BLE Mesh networks.
// Export BLE Mesh network data
const { restoreData } = exportMeshNetworks({ data: [{ name: 'mesh_network' }] })
// Import BLE Mesh network data
importMeshNetworks({ restoreData })
// Get the list of currently existing BLE Mesh networks
const networks = getMeshNetworks() // [{ name: 'network_name', networkId: 'network_id' }]Note
After exporting BLE Mesh network data through exportMeshNetworks, you may need to persist the data. To ensure network security, developers should encrypt the data before storing it, and then decrypt the data when importing.
When importing BLE Mesh network data to a new user through importMeshNetworks, due to iOS system limitations, for the same BLE Mesh device, different users obtain a different Bluetooth deviceId, which makes it impossible to establish a proxy device connection. In this case, the device side needs to continuously broadcast the Node Identity Bluetooth broadcast packet after successful provisioning, so that the plugin can identify the device node and update the Bluetooth deviceId.
2.6 BLE Mesh Network Management
Through getMeshNetworkManager, you can obtain the BLE Mesh network management configurator, which includes functions such as creating / deleting BLE Mesh groups, and obtaining the list of unicast addresses and the list of group addresses of all nodes in the BLE Mesh network.
// Get the BLE Mesh network management configurator
const meshNetworkManager = getMeshNetworkManager({ networkId: 'network_id' })
// Create a BLE Mesh group
const group = meshNetworkManager.createGroup({ name: 'group_name' })
// Delete a BLE Mesh group
meshNetworkManager.removeGroup({ name: 'group_name' })
// Get the list of group addresses
const groups = meshNetworkManager.getGroups()
[{
name, // BLE Mesh group name
address, // BLE Mesh group address
nodes, // Information of the device nodes bound under the BLE Mesh group address
}]
// Get the list of unicast addresses
const unicasts = meshNetworkManager.getUnicasts()
[{
deviceId, // BLE Mesh device id
name, // BLE Mesh device name
localName, // The LocalName data segment in the BLE Mesh device's broadcast data segment
address, // BLE Mesh device unicast address
}]2.7 BLE Mesh Device Provisioning
To achieve BLE Mesh device provisioning, you first need to obtain the BLE Mesh device provisioning configurator provisioningManager, and then complete the provisioning operation through provisioningManager.provision. In addition, you can also implement one-click provisioning of multiple BLE Mesh devices through provisioningManager.batchProvision. Only after a BLE Mesh device completes the provisioning operation is it truly considered to have joined the BLE Mesh network.
// Get the BLE Mesh device provisioning configurator
const provisioningManager = getProvisioningManager({ networkId: 'network_id' })
// Provision a single BLE Mesh device
await provisioningManager.provision({
unprovisionedDevice, // The unprovisioned BLE Mesh device instance
authenticationMethod: AuthenticationMethod.NoOOB, // The OOB security authentication method used during provisioning
})
// Batch provision multiple BLE Mesh devices
await provisioningManager.batchProvision({
unprovisionedDevices, // An array of unprovisioned BLE Mesh device instances
})2.8 BLE Mesh Device Message Communication
After completing BLE Mesh device provisioning, if you want to communicate with the device via messages to implement functions such as controlling the device and obtaining device information, you should first obtain the BLE Mesh proxy device client configurator proxyClientManager. With Bluetooth scanning enabled, use proxyClientManager.hasProxyServer to confirm whether an available proxy device exists nearby, then bind the AppKey in the BLE Mesh network to the Server model of the target device through proxyClientManager.addAppKeyToNode and proxyClientManager.bindAppKeyToModel, and finally send standard BLE Mesh messages to change the state on the target device's Server model or retrieve related information.
// Get the BLE Mesh proxy device client configurator
const proxyClientManager = getProxyClientManager({ networkId: 'network_id' })
// Check whether an available proxy device Server exists nearby
const hasProxyServer = proxyClientManager.hasProxyServer
if (hasProxyServer) {
// Add the AppKey to the target device
await this.proxyClientManager.addAppKeyToNode({
destination, // The unicast address of the target device
})
// Bind the AppKey to the target device's GenericOnOffServer model
await proxyClientManager.bindAppKeyToModel({
destination, // The unicast address of the target device
modelId: ModelIds.GenericOnOffServer, // The modelId of the standard GenericOnOffServer model
})
// Get the on/off state on the target device's GenericOnOffServer model
const resGet = await proxyClientManager.getOnOffStatus({
destination, // The unicast address or group address of the target device
})
console.log(resGet.source, resGet.message.isOn)
// Control the on/off state on the target device's GenericOnOffServer model
const resSet = await proxyClientManager.setOnOffStatus({
destination, // The unicast address or group address of the target device
status, // The on/off state to be set
})
console.log(resSet.source, resSet.message.isOn)
// Developers can also send and receive the most basic opcode and parameters through custom BLE Mesh messages, to implement functions such as Vendor Model.
proxyClientManager.onMessage(({ source, opcode, parameters }) => {
// handle mesh message
})
proxyClientManager.send({
destination, // The unicast address or group address of the target device
opcode, // Opcode
parameters, // Carried parameters
})
}