The proxy protocol is designed to enable nodes to send and receive the Bluetooth Mesh network packets over a connection-oriented bearer. For example, a node could support GATT but not be able to advertise the Mesh Message AD Type. This node will establish a GATT connection with another node that supports the GATT bearer and the advertising bearer, using the Proxy protocol to forward messages between these bearers.
Roles
The proxy protocol defines two roles: the Proxy Server and the Proxy Client.
The Proxy Server is a node that supports a mesh bearer using the Proxy protocol and at least one other mesh bearer. For example, the Proxy Server can forward mesh messages between the advertising bearer and the GATT bearer.
The Proxy Client supports a mesh bearer using the Proxy protocol. For example, the Proxy Client can use the GATT bearer to send mesh messages to a node that supports the advertising bearer.
Filters
The proxy server uses a filter to decide if to forward the message to the proxy client or not. There are 2 types of filters could be used - white list or black list.
A white list filter has an associated white list, which is a list of destination addresses that are of interest for the Proxy Client. The white list filter blocks all destination addresses except those that have been added to the white list.
A black list filter has an associated black list, which is a list of destination addresses that the Proxy Client does not want to receive. The black list filter accepts all destination addresses except those that have been added to the black list.
The white list filter with an empty list is the default filter type. The Proxy Client can change the filter type as well as configure the addresses in the proxy filter.
SDK – Bluetooth Mesh SDK 1.5.0 GA or newer, the latest version are always recommended.
Hardware – At least 3 Bluetooth Mesh compatible boards - EFR32xG12 or EFR32xG13 (x= M, B) based, SLWRB4104A and SLWRB4103A are recommended.
Tools – J-Link RTT viewer or serial terminal for print, if using serial terminal, the parameters are as below:
Baud rate: 115200
Data bits: 8
Stop bit: 1
Flow control: False
Details About The Example
The example is based on the light example which is available in the Bluetooth Mesh SDK. The light example is a proxy server which can be connected to forward Bluetooth Mesh network packets to the proxy client. With modification, the proxy client light will disable the PB-ADV bearer and rely on a proxy server to communicate with the network. For demonstration, 3 nodes are needed in the example - one light, one switch and the proxy client light. Because the PB-ADV bearer is turned off, the proxy client light node cannot receive any commands from the switch directly unless it connects to a proxy server node which is the original light node in this setup.
How It Works
Figure 1 shows how the 3 nodes network works.
Figure 1. Network Topology
How to Identify The Server Node
After the proxy client node being provisioned, it needs to find a proxy server to communicate with the network. For the proxy server nodes, once they are provisioned with PB-GATT bearer or explicitly enabled the proxy feature, they will start advertising with Mesh Proxy Service immediately. So there must be a way for the proxy client to identify if the advertising node is in the same network or not, is the target node or not? The advertisement sent by proxy server nodes has 2 types of payload for the client nodes to parse and decide if to connect - Network ID and node identity, both of which are encrypted. Currently, the SDK doesn't provide a way to decrypt the payload for application layer, so we probably need some other ways to identify the target server node. In the example, it provides 2 workarounds:
Match the network ID without decryption. You can use any Bluetooth scanner to get the proxy service advertisement payload, then record the 8 bytes encrypted network ID. For the client node, it can simply compare the scanned advertisement with the encrypted network ID.
Match the BD_ADDR.
NOTE, this is only the limitation for the time being, this should be deprecated when the SDK exposes the APIs for parsing the encrypted payload.
Network Configuration
You need to provision both nodes and configure them properly before you can verify the functionality. Basically, you need 2 addresses to let the node publish to and subscribe from, follow the setup in below picture.
Figure 2. Typical Setup
Proxy Client Node Work Flow
The work flow of the proxy client node shows in figure 3.
Figure 3. Work Flow
Running The Example
Download the attachment and extract it, create a soc-btmesh-light project in Simplicity Studio with a specified name.
Replace the app.c in your project with the app.c in the attachment.
The example uses the Logging System, if you want to use printf instead, you can comment out the #define USE_LOG_MODULE in app.c.
Flash 2 boards respectively with light and switch, then provision and configure them properly. Remember to enable the proxy feature on the light node.
If using the 1st workaround to identify the proxy server node, do the 6th step, if using the 2nd workaround, do the 7th step.
Find a Bluetooth scanner to scan for the proxy server advertisement and record the 8 bytes encrypted network ID in the payload.
Get the BD_ADDR of the light node which is the proxy server, e.g. using Simplicity Commander or a Bluetooth scanner etc.
If using 1st workaround, modify the #define USE_FAKE_NETWORK_ID 1 and fill the dummy_network_id with the value recorded in the 6th step. If using 2nd workaround, modify the #define USE_FAKE_NETWORK_ID 0 and fill the target_server_node_bd_addr with the value recorded in the 7th step. Build and flash the project to the remaining board.
Factory reset the board if needed, then provision and configure the node properly. After which, it will start to find the target server node and connect to it automatically. You can either check the LCD or the logging via serial/RTT to check the status. Once you see the "Proxy configured" on the LCD or "Proxy configured"/"Filter Length = " depending on what type of filter you are using on the logging, you can operate on the switch node to verify if the proxy client light will react or not. If everything goes well, you should be able to see "Req x" where x indicates the number of received requests sent from the switch, see figure 4.
Bluetooth mesh is based on advertisements, meaning that under the hood the stack is scanning all the time. By default, the scan response events are not passed to the application but they are just consumed by the mesh stack and then silently discarded.
This article illustrated a way to scan BLE advertisements when the Bluetooth mesh stack is running. It uses advertising event filter which allows you to configure which type of events you want to have exposed to the application. It can be used to scan mesh nodes and possibly report the advertisements found to a master node which processes the data.
Implementation
Step1: Configure the advertising event filter by adding this in your boot event handler. For more details about the command refer the Bluetooth Mesh Software API reference manual.
0x7: Enabled advertising packet type mask. This indicates the advertisement could be Connectable undirected, Scannable undirected or, Non connectable undirected advertising.
Step 2: Handle the scan response event by adding following case to the handle_gecko_event() function:
case gecko_evt_le_gap_scan_response_id:
print_scan_resp(&(evt->data.evt_le_gap_scan_response));
break;
Step 3: Add a function that handles the BLE scan responses, here's a sample:
static void print_scan_resp(struct gecko_msg_le_gap_scan_response_evt_t *pResp)
{
// decoding advertising packets is done here. The list of AD types can be found
// at: https://www.bluetooth.com/specifications/assigned-numbers/Generic-Access-Profile
// example of adv data including proxy service data:020106030328180c16281800f03f4f79774c65a2
// (UUID 0x1828)
// 020106-03032818-0c16281800f03f4f79774c65a2
const uint8 proxy_UUID[2] = {0x28, 0x18};
int i = 0;
int ad_match_found = 0;
int ad_len;
int ad_type;
while (i < (pResp->data.len - 1))
{
ad_len = pResp->data.data[i];
ad_type = pResp->data.data[i+1];
if (ad_type == 0x03)
{
// type 0x03= Complete List of 16-bit Service Class UUIDs
if(memcmp(proxy_UUID, &(pResp->data.data[i+2]),2) == 0)
{
ad_match_found = 1;
}
}
//jump to next AD record
i = i + ad_len + 1;
}
if(ad_match_found)
{
for(i=5;i>=0;i--)
{
printf("%2.2x", pResp->address.addr[i]);
}
printf(", RSSI: %d\r\n", pResp->rssi);
}
}
The above code looks through advertising data in scan response events and searches for the mesh proxy UUID 0x1828. If a proxy advertisement is found, the address of the sender and RSSI are printed to debug output.
Testing
In Simplicity Studio, select your radio board, select the latest Bluetooth Mesh SDK and create soc-btmesh-light example project for your device.
Copy and replace the attached file (app.c) into your project.
Compile and flash to your radio board.
Open serial console and observe the print statements.
On another radio board, flash any Bluetooth mesh application consisting of the Mesh Proxy service with UUID 0x1828 and provision it.
This functionality was tested with two BGM13P22 radio boards and v1.4.3 of the Silabs Bluetooth Mesh stack.
This article will introduce how to blacklist nodes from a Bluetooth Mesh network and the related APIs when developing with Silicon Labs Bluetooth Mesh SDK. Blacklisting nodes is an important part of the Bluetooth network management, which prevents the "trash-can-attach" risk. It utilizes the key refresh procedure to remove the nodes whose keys are compromised.
When a node is removed from the network, all remaining nodes would have their keys changed such that the removed node would not have knowledge of the new security credentials being used if that node was compromised after being disposed. This is known as the ”trash-can attack.”
There are 2 ways for Bluetooth Mesh network to remove one or more nodes from the network. The first one is via "Config Node Reset" command, the other way is via key refresh, both ways are supported by Silicon Labs Bluetooth Mesh SDK. Table 1 shows a comparison between these 2 ways.
Config Node Reset
Key Refresh
Network key change
No
Yes, the network key used in the subnet will change
Node state
Unprovisioned
Provisioned, but not in the previous network anymore
Need node(s) function normally
Yes, node(s) should be able to receive commands
No
Table 1. Comparison between Config Node Reset and Key Refresh
In addition to blacklist node(s) from the network, the key refresh procedure is also capatible to refresh the application key(s), which results in blacklisting node(s) from some specific group(s) but remaining in the network. One note for refreshing the application keys, it's impossible to refresh only the application keys without refresh the bound network key.
How Key Refresh Works
If you are interested with the detailed information about how the key refresh procedure is designed and how it works, you can look into the chapter 3.10.4 of the Mesh Profile Specification 1.0.
Because the Silabs Bluetooth Mesh SDK has implemented this and packed the procedure to simple API calls, it's OK to just understand the procedure in general, it has 3 phase:
Receive the net key.
Inform the provisioner that the new key has been received.
Use the new key and revoke the old key.
Related APIs In Silabs Bluetooth SDK
Commands
gecko_cmd_mesh_prov_set_key_refresh_blacklist - this is used to add a node to the blacklist list which is maintained by the stack.
gecko_cmd_mesh_prov_set_key_refresh_appkey_blacklist - same as the above one but for refreshing appkey.
gecko_cmd_mesh_prov_get_key_refresh_blacklist - this is used to check if a node is in the blacklist list which is maintained by the stack.
gecko_cmd_mesh_prov_get_key_refresh_appkey_blacklist - same as the above one but for refreshing appkey.
gecko_cmd_mesh_prov_key_refresh_start - command to start the key refresh procedure, nodes in the blacklist list will get blacklisted.
Test Class Commands
The test class commands are for developing and testing purpose, it's NOT recommended to use in the production firmware.
gecko_cmd_mesh_test_update_local_key - this is used to update the key locally by a node.
gecko_cmd_mesh_test_prov_prepare_key_refresh - this command will set the network key and the application key(s) if any which will be used for the next key refresh procedure.
Events
gecko_evt_mesh_prov_key_refresh_node_update_id - there are 3 parameters carried in this event, key (network key index), phase (which phase the node has moved into) and uuid (UUID of the node). This event indicates that the node has moved to the specific phase.
gecko_evt_mesh_prov_key_refresh_phase_update_id - this event indicates that the whole network has moved to the specific phase.
gecko_evt_mesh_prov_key_refresh_complete_id - this event indicates that the key refresh procedure has completed.
Typical Flow
Below is a pseudo code to demonstrate to blacklist 3 nodes with UUID - uuid1, uuid2 and uuid3.
#define BLACKLIST 1
#define UUID_LEN 16
#define NET_KEY_INDEX 0
#define APP_KEY_NUM_TO_REFRESH 0
struct gecko_msg_mesh_prov_set_key_refresh_blacklist_rsp_t *pBgRet = NULL;
struct gecko_msg_mesh_prov_key_refresh_start_rsp_t *pKeyRefStartRet = NULL;
pBgRet = gecko_cmd_mesh_prov_set_key_refresh_blacklist(netkey_id,
BLACKLIST,
UUID_LEN,
uuid1);
check the result value, pBgRet->result.
pBgRet = gecko_cmd_mesh_prov_set_key_refresh_blacklist(netkey_id,
BLACKLIST,
UUID_LEN,
uuid2);
check the result value, pBgRet->result.
pBgRet = gecko_cmd_mesh_prov_set_key_refresh_blacklist(netkey_id,
BLACKLIST,
UUID_LEN,
uuid3);
check the result value, pBgRet->result.
pKeyRefStartRet = gecko_cmd_mesh_prov_key_refresh_start(netkey_id,
NET_KEY_INDEX,
APP_KEY_NUM_TO_REFRESH,
NULL);
check the result value, pKeyRefStartRet->result.
while(1) {
check the events from the stack.
switch(evt_id) {
case gecko_evt_mesh_prov_key_refresh_node_update_id:
record any information carried by the event if needed.
break;
case gecko_evt_mesh_prov_key_refresh_phase_update_id:
record any information carried by the event if needed.
break;
case gecko_evt_mesh_prov_key_refresh_complete_id:
check the e->data.evt_mesh_prov_key_refresh_complete.result to see if success?
record the new network key index
break;
}
}
...
Example
The project in KBA_BT_0509: Bluetooth Mesh Host Provisioner implements the blacklisting feature, you can use it to try out blacklisting nodes from the network. If you don't have time to go through and understand the whole project, you can just poll out the stuff in blacklisting_devices.c which contains all the blacklisting related code.
A provisioner plays an important role in the Bluetooth Mesh network, which creates and manages the network by adding, configuring and removing devices into/from the network. This article will provide you a ncp host example which works with the ncp target to act as the provisioner. For more information about the ncp mode and ncp host and target, please go through KBA_BT_1602: NCP Host Implementation and Example.
Prior to this example, we have the SoC mode provisioner example introduced in KBA_BT_0501: BT Mesh embedded provisioner example, it has the full implementation of provisioning and configuring a device into a network and is easier to understand and more suitable for beginners. However, it has below limitations:
In SoC mode, only 14 devices can be added to the same network, while in ncp mode, it supports to add up to 512 devices for now.
Application and network configuration are fixed at the compiling time, any changes to the network require to re-build and flash the provsioner.
Due to the limitation of the resources on the WSTK, it has limited features.
Given the above limitations, the host network manager was developed with below ideas in mind.
Make it as automatic as possible so that it can be used for automatic testing.
Separate the application and configuration, so that it doesn't need to rebuild the application to apply any configuration changes to the network.
Configuration file can be changed at any time, the application will check if needs to reload them before issuing a command.
Robustness improvement, every process may fail because of any reason. Retry and some recovery mechanisms are needed to make the network more robust.
A console to receive commands from the user. Easy to add any customized command to extend the application.
Capabilities
The host network manager supports below functionalities:
Create network and application keys
Provision multiple devices into a network simultaneously
Configure multiple devices simultaneously
Add application keys
Bind application keys to models
Set publication address to models
Add subscription addresses to models
Set default TTL value
Set relay/friend/proxy feature on or off
Set the network/relay transmission - count and interval
Set Secure Network Beacon on or off
Remove devices from a network via node reset procedure
Blacklist devices from a network via key refresh procedure
Set the light status
On or off
Lightness
Color temperature
NOTE: Removing a node is different than blacklisting a node from the network. Removing is like to ask the node to leave the network actively - provisioner sends a command to force the node to factory reset itself, while blacklist is passively being blacklisted from the network - provisioner sends packets to the reset of the nodes to migrate to a new network key, see table 1. For more information, you can go through KBA_BT_0510: Blacklisting Nodes From Bluetooth Mesh Network.
Remove
Blacklist
Network key change
No
Yes
Before the procedure
Target needs to work normally
Doesn't matter
After the procedure
Factory reset
Remaining unchanged
Table 1. Comparison between removing and blacklisting
SDK – Bluetooth Mesh SDK 1.6.0 GA or newer, the latest version is always recommended.
NCP target – WSTK with Bluetooth Mesh compatible radio boards - EFR32xG12, EFR32xG13 or EFR32MG21 (x= M, B) based.
NCP host - POSIX compatiable machine to run the host application, THIS HAS ONLY BEEN TESTED ON Linux and MacOS. Running the application on Windows or other platforms probably needs some porting effort.
Libraries
This project uses the open source library for parsing the JSON configuration files and glib for the data structures. Users needs to install the libraries properly before using the example.
The architecture of the host network manager is as shown in figure 1. Below is a brief introduction to each module in this diagram.
Event Handler - read BGAPI events from NCP target and dispatch them to corresponding modules.
Generic Config Parser - An abstract layer for parsing different types of config files, which provides the configuration to all other modules.
Configuration Database - Store all the configuration, including network and nodes configuration
MNG - Loads the configuration from CFG part and deploy to the network.
Logging - Receives data from other layers and writes to the log file.
CLI - Receives user input.
Limitation of this design - Only ONE subnet is supported, while multiple subnets feature is supported by the Bluetooth Mesh SDK. It's because the requirements for multiple subnets in practice is not very common yet, so just leave it for future implementation.
Generally, there are 3 parts in the program, CLI, MNG and CFG.
CLI
The command line interface part receives commands from user and pass them to MNG for further processing if needed.
Supported commands
Conventions:
Each [] stands for an argument iteam, some of them are mandatory to present and some are not, in which case, a default value of the argument is applied.
Argument followed by ... means variable number of the argument.
Command
Args
Defaults
Usage
Description
sync
[1/0]
1
sync
Start or stop synchronizing the network configuration with the JSON configuration files
reset
[1/0]
0
reset
Reset the device, if argument is 1, erase the storage as well, known as factory reset
info
[addr...]
/
info 0x003a
If no argument is given, shows the overall configuration of the network, if address is given, shows the specific configuration to the node, including UUID, Device key etc.
q
\
/
q
Quit the program
freemode1
[on/off]
on
freemode on
Turning on/off the free mode.
help
\
\
help
Print the usage of all commands.
status
\
\
status
Print the device status.
rmall
\
\
rmall
Remove all the nodes from the network
clrrb
\
\
clrrb
Clear the RM_Blacklist fieldof the nodes
seqset
combination of a, r, b and -
\
seqset ar-
determine the sequence of loadding the adding/removing/blacklisting/none actions.
loglvlset
[e/w/m/d/v] [1/0]
\
loglvlset w
Log with priority "warning" or higher will be sent to the log file, the second parameter determines if the logging will be sent to printf (stdout if not redirect)
Table 2: Network Configuration Commands
Command
Args
Usage
Description
onoff
[on/off] [addr...]
onoff on 0x1203 0x100c
Set the light onoff status, if no address is given, set to all light nodes
lightness
[pecentage] [addr...]
lightness 50 0x1203 0x100c
Set the light lightness status, if no address is given, set to all light nodes
colortemp
[pecentage] [addr...]
colortemp 30 0x1203 0x100c
Set the light color temperature status, if no address is given, set to all light nodes
Table 3: Lighting Control Commands
When freemode is on, the device will start scanning for unprovisioned device beacon and record the device information to the backlog in the nodes configuration file if found.
MNG
The MNG part is the core part of the application, which coprate with the other two parts and make sure the network is properly configured according to the configuration files and the received commands.
Features
Simultaneously Provision and Configure Devices
Silicon Labs Bluetooth Mesh SDK supports this feature, as most of the demos uses a 'single thread' way to do it (provision one -> configure one -> provision another -> ...), users may be misled that provision/configure the next device must wait for the compete of the previous one.
To benefit from this, you need to set the 2 fields in the "Memory Configuration" in the NCP target isc file.
Max Prov Sessions - this determines how many devices can be provisioned by the provisioner simultaneously. There is a define #define MAX_PROV_SESSIONS 4 in adding_devices.h of the host project, this value must be equal or less than the setting in the NCP target memory configuration.
Max Foundation Client Cmds - this determines how many nodes can be configured by the provisioner simultaneously. There is a define #define MAX_CONCURRENT_CONFIG_NODES 6 in async_config_client.c of the host project, this value must be equal or less than the setting in the NCP target memory configuration.
Below is a rough time comparison of provisioning and configuring a 50-node network between using 'single thread' way and the asynchronous way. The time itself is meaningless because it heavily depends on the environment, how you configure each node, how many retries for timeouts and interval between retries etc..
'Single thread' way - around 20 minutes
Asynchronous way - around 4.5 minutes
Retry
Due to the nature of Bluetooth Mesh technology and the fact that wireless communication is heavily affected by the environments such as packet collision, commands sent to the nodes may be lost. Retry mechanism on the application layer has been implemented to increase the robustness. However, given that retry probably won't solve the error other than timeout or out of memory, so the current implementation will only retry on timeout and out of memory situation. For other errors, it will end the current operation immediately and record the failure status to the node configuration file, so developers could check the error and determine how to deal with it afterwards. It is easy to add any error events to retry, add any specific error event to below the timeout event case in each state callback switch block.
The define symbols in the projconfig.h file determines the maximum retry times for each specific configuration process.
CFG
An example of the configuration files is available in the ${PROJECT_ROOT}/tools/mesh_config/example folder, you could copy it and use it as starting point to configure your network and nodes.
Self Configuration
The content in this file describes how the provisioner should configure itself and how to create the network, see table 4.
What's it
Key
Value
Description
Last sync time1
SyncTime
uint32
Time stamp that the appliaction write to the file most recently
IV index
IVI
uint32
Keys
\
\
Details in Table 5 below
Time To Live
TTL
uint8
Network Transmit Count
TX Parameters - Count
uint8
[0, 7]
Network Transmit Interval
TX Parameters - Interval
uint8
[10, 320]@step10
Config timeout for non-LPN nodes
Config Timeout - Normal
uint16
in milliseconds
Config timeout for LPN nodes
Config Timeout - LPN
uint16
in milliseconds
Publication Groups
PubGroups
uint16array
Not Used Yet
Subscription Groups
SubGroups
uint16array
Not Used Yet
Table 4. Provisioner Config File Content
What's it
Key
Value
Description
Reference ID2
RefId
uint16
Key Index
Id
uint16
Key Value
Value
16BL uint8array
Created successfully?
Done
bool
Table 5. Key Content
Network & Nodes
The content of this file describes how the nodes will be processed, including adding, removing, configuring and blacklisting.
What's it
Key
Value
Description
Last sync time1
SyncTime
uint32
Time stamp that the appliaction write to the file most recently
UUID
UUID
16BL uint8array
16 bytes device UUID of the node
Unicast address
Address
uint16
unicast address of the primary element of the node, 0 for unprovisioned/unassigned node
Error bit masks
Err
uint32
error bit masks to record where the last failure is
Template Identifier
Template ID
uint8
template identified by ID to load to the node
Removing and Blacklisting Flags
RM_Blacklist
uint8
bit 0 indicates if to blacklist the node, bit 4 indicates if to remove the node, other bits reserved
Funtionality
Funtionality
uint8
Funtionality of the node, a light, sensor or others
Configured Flag
Done
uint8
Indicates if the node has been configured properly
Time To Live
TTL
uint8
Network Transmit Count
TX Parameters - Count
uint8
[0, 7]
Network Transmit Interval
TX Parameters - Interval
uint8
[10, 320]@step10
Features supported by the node
Features - *
Structure
Indicates if the feature is supported (1) or not (0)
Model Key Binding settings
Bind Appkeys
uint16array
Appkey reference IDs to bind to the models
Publication settings
Publish To - *
Structure
Parameters for publication
Subscription settings
Subscribe From
uint16array
Addresses the nodes subscribe from
Enable/disable secure network beacon
Secure Network Beacon
uint8
1 to enable, 0 to disable
Backlog
Backlog
Nodes
Nodes in backlog won't be processed
Table 6. Network & Nodes Config File Content
Template
The configuration of one single node might be long, and multiple nodes may have the same configuration just like the concept of group. So the configuration item in the template file provides the configuration for groups. You could add the "Template ID" field to the node and fill it with the specific reference ID of the group. For the case where a specific configuration is both defined in the node field and the group field. The configuration in the node field will be used.
By checking the last modification time against last synchronized time to know if the configuration is changed out of the program.
The real id is allocated when the key is created successfully, however, in most of the cases, configuration of the network happens before it. So the keys are referenced by the RefId across the configuration files.
Security
Security is extremely important for your products and the Bluetooth Mesh network. The application aims to provide an example or a starting point for developing this sort of application, so it stores the sensitive data including the network and application keys into the file without encryption. That SHALL NEVER be used when developping the real products. How to securely store the data to the file and make the file to be safe is left for developers respectively.
Secure & Insecure NCP
The provisioner supports both secure and insecure NCP, which are 2 ways of commnicating between the NCP host and target provided by Silicon Labs. With secure NCP, the ncp secure daemon must be running and user needs to feed the socket file path with parameter if it's encrypted to the application. With the insecure NCP, user needs to feed the UART port and baud rate.
Utils
This part can be used by any other parts as utils.
Error Code
The error code design is to provide as much information as possible from the return value. Most of the functions in the program returns a err_t which can either be a 64-bit or 32-bit unsigned value. With separating the bits into different fields, it could contain multiple information pieces. The design in this application divides the unsigned value into 3 fields - error code, line and file information where the error code is generated. There are several functions in the err.h and err.c for generating and parsering the unsigned value. In general, when there is a specific error happens, return the error code surrounded by err(x) macro, when getting a non-zero (not ec_success) unsigned return value, use elog(x) to print the error information to the log file or use eprint(x) which calls printf rather than writting to the log file. Figure 2 shows the elog output.
Figure 2. Error Information
Logging
Logging has the level feature which is inspired from Android logging system. The threshold of the logging is settable via 'loglvlset' command, as a result of which, the logging messages with priority lower than the threshold will not be sent to the logging file. See the table 7 for the logging message types with priorities in descending order.
The logging messages will be written to the file system, the path is specified when initializing the logging.
The NCP target owns the device database of the network, it's important to set the memory configuration properly so that it can actually store the necessary information of the whole network for the target size. In other words, the memory configuration determines how large your network could be.
Below is an example of setting the memory configuration, in which the network target size is 128. You need to set AT LEAST below items to the memory configuration file, which is in the {PROJECT_NAME}.isc file in your ncp target project.
Item
Value
Note
Feature bitmask
0x0001
RPL size
128(0x80)
set to the expected network size if possible
Net Cache Size
128(0x80)
set to the expected network size if possible
Max Provisioned Devices
128(0x80)
set to the expected network size
Table 8. Memory Configuration of NCP Target
Furthermore, there are 2 important settings in NVM3 which is the persistent storage solution used in the Bluetooth Mesh stack. You possibly need to increase the settings below if you increase the network target size. For more information, please go through the AN1135: Using Third Generation Non-Volatile Memory (NVM3) Data Storage.
NVM3_DEFAULT_CACHE_SIZE
NVM3_DEFAULT_NVM_SIZE
Usage Example for Typical Scenarios
Get It Running
You need to do at least below steps to get it running.
Create a "NCP - Mesh Empty Target" or "NCP - Secure NCP Mesh Empty Target" example based on the board you use.
Modify the memory configuration mentioned above to meet your target network size requirement.
Properly set the "Max Prov Sessions" and the "Max Foundation Client Cmds" in the memory configuration file, and make sure Max Prov Sessions >= MAX_PROV_SESSIONS and Max Foundation Client Cmds >= MAX_CONCURRENT_CONFIG_NODES
Build the program and flash it to your board. Connect it to your host platform and make sure the UART is working.
Make sure you have all the dependent libraries installed, and download the application.
Speicify the JSON configuration file pathes to SELFCFGFILE_PATH and NWNODES_FILE_PATH symbols in _projconfig.h file. You could specify a non-existing path so the application will create the files with basic configurations and you could modify the configuration afterwards. Note, the folder should exist already.
Compile and run the application with proper argument according to your setup. Once you have successfully run it once, the arguments will be written to a cache file, the next time you can emit them if you don't want to change the arguments.
A console should start and you could type "help" to get the usage.
Record Devices Nearby
This could be the first step you use the program. Make sure you have the unprovisioned device placed in the direct radio range to the provisioner and they are sending the unprovisioned device beacon. Then you can do the below steps to record them.
Start the program.
Type freemode on to start recording. If any unprovisioned device beacon is received, it will store the device information to the backlog of the node configuration file.
Type freemode off when all the devices are recorded to the backlog.
Move Devices from Backlog to Primary Subnet
As mentioned above, the nearby devices recorded by freemode will be added to backlog. You need to cherry pick those you want to add to your network from the backlog to the primary subnet field.
Open the nodes configuration file.
Move the nodes you want to operate onto the first item of "Subnets"
Change the "Template ID" field of each node based on what configuration you want to apply to the node. Certainly, you could change the configuration as well.
Adding/Configuring Device(s)
Make sure you have properly set the configuration to all the nodes in the node configuration file.
Start the program if not yet.
Type "sync" to start adding them to the network and configuring them.
Blacklisting Node(s)
Assuming that you have established a network because we cannot blacklist nodes if they are not in the network yet.
Open the nodes configuration file.
Find the node(s) you want to blacklist from the netowkr and change the "RM_Blacklist" field to "0x01". Note, the address of the node SHALL NOT be 0, in which case the node is not yet added to the network. Then save it.
Make sure 'b' is in the sequence, you could optionally set it as the first priority action by "seqset" command.
Type "sync", once it finishes, you will get the result in your terminal.
Removing Nodes(s)
This procedure is very similar to the last one - Blacklisting Node(s), the only difference is to modify the "RM_Blacklist" Field to "0x10"
Change Configuration to Node(s)
The "Done" field indicates if the node has been configured properly, to change the configuration of nodes, follow the below steps.
Open the nodes configuration file.
Find the node(s) you want to configure and modify the configuration fields, then change the "Done" field to 0x00.
type "sync", the program will load the new configuration and apply to the nodes.
Lighting Control
Once you have the network and the nodes configured, the node functionality is stored in the configuration file respectively. Then you can use the CLI commands to control the light status.
To set a single node or nodes on, type the command "onoff on 0x000x...", where 0x000x are the unicast address of the nodes.
To set a group nodes on, type the command "onoff on 0x000x...", where 0x000x are the group address that the group subscribe from.
This article lays out the different ways of doing device firmware updates (DFU), especially over-the-air updates (OTA), when using NCP Mode in your design. We will use the NCP-target-empty example project as the starting point. Normally the NCP empty example just acts as a bridge between the NCP host and the BLE stack running inside an EFR32 device. In these cases, OTA logic has been included in the NCP-target-empty firmware.
1.1 Adding a bootloader to example projects
When starting with software examples in Simplicity Studio, the project will not contain a bootloader by default. To get the bootloader, either flash an NCP target - Empty demo or create and flash a Gecko Bootloader example project for your part.
1.2 Creating Upgrade Images of your project
SDK examples provide scripts, which generate .gbl-files, create_bl_files.bat/.sh for Windows and Linux/Mac respectively. The images (application.gbl, full.gbl and possible secure variants) are created into output_gbl folder.
1.3 OTA Client
For methods other than the UART DFU, we will use the Blue Gecko mobile app as the OTA client to perform the upgrade. A guide to using the app can be found here.
2. Firmware Update Methods
2.1 UART DFU
This is probably the most used firmware update method in NCP-mode. A Gecko Bootloader image (.GBL file) containing the new firmware is written to target device using UART and BGAPI binary protocol. The target device needs to be programmed with the Gecko Bootloader as BGAPI UART DFU Bootloader.
The default configuration, suitable for testing with Wireless Starter Kit, is as follows:
UART Option
Default
USART
USART0
Baud rate
115200
TX pin
PA0
RX pin
PA1
HW flow control
OFF
UART enable port
PA5 (VCOM_ENABLE)
The UART DFU process follows these basic steps:
Boot the target device into DFU mode (dfu_reset(1)).
Wait for DFU boot event.
Send command DFU Flash Set Address to start the upgrade (set as zero, offsets are calculated automatically).
Send the whole Gecko Bootloader image (.GBL) using DFU flash upload.
After sending image, the host sends command DFU upload finish.
Finally, the host resets target to normal mode dfu_reset(0).
An NCP host example is provided with the SDK at <StudioPath>\<version X>\developer\sdks\gecko_sdk_suite\<version>\app\bluetooth\examples_ncp_host\uart_dfu. For more information about compiling and developing host examples, see AN1042. The host example compiles to an executable, which takes the COM port number, baud rate and full.gbl file as arguments.
2.1.1 Testing UART DFU
Create a new NCP-empty-target project for your part. Here a BGM13P22 module is used.
Create a new BGAPI UART DFU Bootloader project for your part.
Flash the <projectname>-combined.s37 file of the bootloader project to your part first.
Build and flash the default NCP-empty-target project to your part. At this point, you should be able to connect to your part with e.g. BGTool to verify that it's running. You should not see any advertisements by default.
Next, we'll add functionality to the NCP-target project, by including the following code in function local_handle_event in main.c:
// In the switch-statement
case gecko_evt_system_boot_id:
{
// Start advertising automatically at boot (just to make testing easier)
gecko_cmd_le_gap_start_advertising(0, le_gap_general_discoverable,le_gap_connectable_scannable);
}
break;
This will make the device start advertising with name "BLE Device" by default.
6.Build the project again and run the create_bl_files script.
7. Navigate to the uart-dfu host example directory mentioned above and compile the host project with e.g. mingw32-make.
8. Copy the full.gbl image to the \exe directory, which now also contains the executable program.
9. Run the program from using a command like utility.
uart-dfu.exe <your port> 115200 full.gbl
10. After the upgrade is finished, you should see "BLE Device" from, for example, Blue Gecko mobile app Bluetooth Browser. -Success!
2.2 AppLoader
The Apploader is a simple application with a minimal Bluetooth stack, that handles the upload process. The Apploader uses the API of the Gecko Bootloader to decode the GBL files and to store the application image in the flash.
For NCP projects, AppLoader should be linked in the project C/C++ Build->Settings->GNU ARM C Linker->Miscellaneous->${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<partname>/GCC/binapploader.o} and copied there from the ${StudioSdkPath}/protocol/bluetooth/lib/<partname>/GCC/ SDK directory. The Silicon Labs OTA service should also be added to your GATT either via the GATT Configurator or gatt.xml file.
The standard OTA DFU sequence implemented in the AppLoader goes as follows:
App is running.
Device is reset into DFU mode. In this mode the bootloader will start the Apploader instead of the Application.
The Apploader advertises and waits for a Bluetooth connection.
The AppLoader waits for the OTA start command (ota_control characteristic).
The Apploader starts receiving the GBL file (using ota_data characteristic).
The headers of the GBL file are stored in Slot 0 to be parsed.
After parsing the headers, the rest of the GBL file is decoded on-the-fly, and the application is copied right to the application area, overwriting the old application.
The Apploader receives the OTA end command and restarts the device in normal mode.
To implement this and test it, you need to capture the write request to ota_control in local event-handling loop to get to step 2. Connection closed event needs to be handled as well.
/* Check if the user-type OTA Control Characteristic was written.
* If ota_control was written, boot the device into Device Firmware Upgrade (DFU) mode. */
// static uint8_t boot_to_dfu = 0; defined at the top
case gecko_evt_gatt_server_user_write_request_id:
if(evt->data.evt_gatt_server_user_write_request.characteristic == gattdb_ota_control) {
/* Set flag to enter to OTA mode */
boot_to_dfu = 1;
/* Send response to Write Request */
gecko_cmd_gatt_server_send_user_write_response(evt->data.evt_gatt_server_user_write_request.connection,
gattdb_ota_control,
bg_err_success);
/* Close connection to enter to DFU OTA mode */
gecko_cmd_le_connection_close(evt->data.evt_gatt_server_user_write_request.connection);
}
break;
/*-----------------------------------------------*/
// In connection_closed event to enter OTA mode
if (boot_to_dfu) {gecko_cmd_system_reset(2);}
This is implemented in the attached Apploader_OTA_main.c file. The procedure is also described in AN1086 section 3.6.
For testing, flash the modified NCP-empty project to your kit, make another example project for the same part, e.g. SoC-Thermometer and generate the GBL files with the script as described in the beginning sections of this article. Now you should be able to perform OTA with Blue Gecko app and see that the new example is running.
2.3 Application-level OTA
In addition to the basic UART and OTA DFU solutions discussed above, it is possible to implement the firmware update functionality completely in the user application.
The main difference here compared to AppLoader based OTA above is that there is no separate DFU mode and step 2 in the above list is not needed at all. The GBL file is uploaded to the target device under the control of the user application. In this example, the file upload is done using the Silicon Labs proprietary OTA service (as specified in AN1086), but it is possible to use a customer specific service and protocol to handle the file upload.
Some of the benefits of this approach are:
The user application remains fully functional while the OTA image is being uploaded.
It's possible to implement customer specific OTA service/protocol (with application level security if needed).
EM2 deep sleep is supported during OTA upload. *
normal BLE security features (link encryption, bonding...) can be used.
* Sleep and BLE encryption/bonding are not supported by AppLoader to reduce the flash footprint.
An obvious disadvantage of this solution is the requirement to have dedicated flash space available to be used as the download area.
To use this approach, your device needs to be programmed with a suitable Gecko bootloader. When creating the bootloader project select Internal Storage Bootloader (single image on 512kB/1MB device), depending on the size of internal flash in your device.
Gecko bootloader has a key part in the OTA update. After GBL file is uploaded, it is Gecko bootloader that takes care of parsing the GBL file and installing the new firmware. The bootloader is also needed during the OTA file upload.
Gecko bootloader has an application interface exposed through a function table in the bootloader. This means that the user application can call functions implemented in the bootloader, even though the application is running in normal mode. In other words, the bootloader API functions are called from the user application context, but the implementation is in the Gecko bootloader project. As a practical example, the user application can call function bootloader_writeStorage to write data into the download area, without even knowing where the download area is physically located.
A list of the key bootloader API calls needed to implement OTA update is found in AN1086, Chapter 4. The commands are also shown below in short.
// Bring in needed bootloader functions
#include "btl_interface.h"
#include "btl_interface_storage.h"
// Erase download slot before update started
bootloader_eraseStorageSlot(0);
// Write 0 to ota_control characteristic -> init
bootloader_init();'
// Write received bytes to download area
bootloader_writeStorage(...);
// When 3 is written to ota_control, the update ends and you verify the image
bootloader_verifyImage(0, NULL);
// Specify slot of new image
bootloader_setImageToBootload(0);
// Reboot and perform update
bootloader_rebootAndInstall();
2.3.1 Implementing and testing application-level OTA
Changes made in the NCP-target-empty example:
In GATT Configurator (.isc):
Set Device Name characteristic variable length checkbox checked and length to 10.
Drag&Drop Silicon Labs OTA service from the left hand side list
change both characteristic types to user
ota_data to variable length and length 255
add write property for ota_data
Save and Generate
New files and include paths that need to be added into the project (versus having just binapploader.o linked):
files btl_interface.c and btl_interface_storage.c need to be added to the project so that the Gecko bootloader API can be used
these can be copied from <studio install>\developer\sdks\gecko_sdk_suite\vX.Y\platform\bootloader\api
following include paths added in the C build settings
"${StudioSdkPath}/platform/bootloader"
"${StudioSdkPath}/platform/bootloader/api"
Changes in main.c:
The NCP empty example includes a skeleton for adding customized event handling code, it is the function local_handle_event. This function is called whenever an event is caught in the main loop. The default implementation is empty, it is merely a placeholder for user code.
All the changes in main.c are in the local_handle_event(), with some additional includes and definitions added just before this function definition.
To support OTA in the NCP firmware, the following event handlers are implemented:
gecko_evt_system_boot_id
gecko_evt_hardware_soft_timer_id
gecko_evt_gatt_server_user_write_request_id
gecko_evt_le_connection_closed_id
See attached example in file app_level_OTA_main.c.
2.3.2 How it works
The implementation follows the same idea that is described in application note AN1086. The boot event handler initializes GPIOs and checks the state of button PB0. If button is pressed at the time of reboot, then the download area is erased by calling bootloader_eraseStorageSlot(0);. The boot event also sets the device name dynamically and starts advertising automatically so that OTA can be tested without any NCP host at all.
Soft timer is only used for LED blinking. A soft timer is started if the download area is erased. The soft timer handler will then simply toggle the LED pin state.
The user write request event handler is where most of the OTA work is done. Note that the type of ota_data characteristic was changed to type user in GATT configurator. Writes to ota_control characteristic will start and terminate the OTA update. Only control values 0 and 3 need to be handled, no other control values are supported by this example.
When OTA image data is received (write to ota_data), the event handler writes the data directly to the internal flash memory using Gecko bootloader API (bootloader_writeStorage).
When client writes the value 3 to ota_control indicating that all the data has been sent, the application verifies the received GBL file by calling bootloader_verifyImage. GBL file includes checksum which makes it possible to check if the file was corrupted.
After successful GBL image upload, the disconnect event triggers the actual firmware update. If the verification was successful, the new GBL image is installed by calling:
bootloader_setImageToBootload(0);
bootloader_rebootAndInstall();
If the image verification failed, the application does not try to install or reboot. Instead, it restarts advertising and includes the error code from the verify function in the device name.
To test the verify feature, you can try OTA update with a corrupted file. The file truncated.gbl is a GBL file from the project that has been intentionally modified so that it does not pass the check (some data has been cut from the end of the file). If you try OTA update with this file, the expected result is that the application will not change and it will restart advertising with name “err XXXX”. You can then erase the download area and try again with a valid GBL file.
2.3.3 How to test it
Preparations:
Build and flash the bootloader built with default settings (*combined.s37).
Flash the application image (*.hex).
Copy the provided GBL files to your phone.
First, verify the device starts advertising with name “NCP APP 1”. You can also use BGTool to test that the device is responding to BGAPI commands.
To test OTA, you need to manually erase the download area. To do this, keep PB0 pressed and reset the kit. LED1 turns on and after a short delay it starts blinking. The delay is because of the flash erase (~256kB area) which takes time to complete.
The device should now advertise with name “NCP APP 1*”.
Now you can run OTA using the Blue Gecko app. OTA is performed using one single file (fullv1.gbl). In the OTA options, use the partial update which asks you to specify only one GBL file. Select file fullv2.gbl to change the application from version 1 to version 2.
After the OTA upload is complete, you press END button on the mobile app. At this point, the connection is closed and the NCP firmware completes the firmware update. Gecko bootloader is used to install the new image from the download slot.
Installation of the new image takes about 8 seconds and then the device reboots with new firmware installed. At this point, you should see it advertising with a different name “NCP APP 2”.
You can repeat the process and do another update to the original version by using file fullv1.gbl.
Remember that you need to erase the download area before each OTA update.
2.4 Bluetooth in-place OTA DFU
The download area must not overlap with the user application and therefore the above DFU solution is not applicable to devices or modules based on the EFR32xG1, as they have smaller flash size (256 kB). For EFR32xG1, the Bluetooth in-place OTA DFU Bootloader configuration is used as a default. In this configuration, the upper half of the main flash, normally used to hold the Bluetooth application, is repurposed as a storage area while a Bluetooth stack upgrade is downloaded. The flash layout is illustrated in Fig. 3.1. in AN1086 Section 3.2. For these parts, you can follow the same workflow as described in the Apploader section, but make sure to flash the Bluetooth in-place OTA DFU Bootloader example project (or demo) first.
Bluetooth Knowledge Base
KBA_BT_0512: Bluetooth Mesh Proxy Client Example
Introduction
Proxy protocol
The proxy protocol is designed to enable nodes to send and receive the Bluetooth Mesh network packets over a connection-oriented bearer. For example, a node could support GATT but not be able to advertise the Mesh Message AD Type. This node will establish a GATT connection with another node that supports the GATT bearer and the advertising bearer, using the Proxy protocol to forward messages between these bearers.
Roles
The proxy protocol defines two roles: the Proxy Server and the Proxy Client.
The Proxy Server is a node that supports a mesh bearer using the Proxy protocol and at least one other mesh bearer. For example, the Proxy Server can forward mesh messages between the advertising bearer and the GATT bearer.
The Proxy Client supports a mesh bearer using the Proxy protocol. For example, the Proxy Client can use the GATT bearer to send mesh messages to a node that supports the advertising bearer.
Filters
The proxy server uses a filter to decide if to forward the message to the proxy client or not. There are 2 types of filters could be used - white list or black list.
A white list filter has an associated white list, which is a list of destination addresses that are of interest for the Proxy Client. The white list filter blocks all destination addresses except those that have been added to the white list.
A black list filter has an associated black list, which is a list of destination addresses that the Proxy Client does not want to receive. The black list filter accepts all destination addresses except those that have been added to the black list.
The white list filter with an empty list is the default filter type. The Proxy Client can change the filter type as well as configure the addresses in the proxy filter.
Environments
Details About The Example
The example is based on the light example which is available in the Bluetooth Mesh SDK. The light example is a proxy server which can be connected to forward Bluetooth Mesh network packets to the proxy client. With modification, the proxy client light will disable the PB-ADV bearer and rely on a proxy server to communicate with the network. For demonstration, 3 nodes are needed in the example - one light, one switch and the proxy client light. Because the PB-ADV bearer is turned off, the proxy client light node cannot receive any commands from the switch directly unless it connects to a proxy server node which is the original light node in this setup.
How It Works
Figure 1 shows how the 3 nodes network works.
Figure 1. Network Topology
How to Identify The Server Node
After the proxy client node being provisioned, it needs to find a proxy server to communicate with the network. For the proxy server nodes, once they are provisioned with PB-GATT bearer or explicitly enabled the proxy feature, they will start advertising with Mesh Proxy Service immediately. So there must be a way for the proxy client to identify if the advertising node is in the same network or not, is the target node or not? The advertisement sent by proxy server nodes has 2 types of payload for the client nodes to parse and decide if to connect - Network ID and node identity, both of which are encrypted. Currently, the SDK doesn't provide a way to decrypt the payload for application layer, so we probably need some other ways to identify the target server node. In the example, it provides 2 workarounds:
NOTE, this is only the limitation for the time being, this should be deprecated when the SDK exposes the APIs for parsing the encrypted payload.
Network Configuration
You need to provision both nodes and configure them properly before you can verify the functionality. Basically, you need 2 addresses to let the node publish to and subscribe from, follow the setup in below picture.
Figure 2. Typical Setup
Proxy Client Node Work Flow
The work flow of the proxy client node shows in figure 3.
Figure 3. Work Flow
Running The Example
Figure 4. LCD Status
KBA_BT_0508: Scanning BLE beacons in Bluetooth Mesh mode
Introduction
Bluetooth mesh is based on advertisements, meaning that under the hood the stack is scanning all the time. By default, the scan response events are not passed to the application but they are just consumed by the mesh stack and then silently discarded.
This article illustrated a way to scan BLE advertisements when the Bluetooth mesh stack is running. It uses advertising event filter which allows you to configure which type of events you want to have exposed to the application. It can be used to scan mesh nodes and possibly report the advertisements found to a master node which processes the data.
Implementation
Step1: Configure the advertising event filter by adding this in your boot event handler. For more details about the command refer the Bluetooth Mesh Software API reference manual.
0x7: Enabled advertising packet type mask. This indicates the advertisement could be Connectable undirected, Scannable undirected or, Non connectable undirected advertising.
Step 2: Handle the scan response event by adding following case to the handle_gecko_event() function:
Step 3: Add a function that handles the BLE scan responses, here's a sample:
The above code looks through advertising data in scan response events and searches for the mesh proxy UUID 0x1828. If a proxy advertisement is found, the address of the sender and RSSI are printed to debug output.
Testing
In Simplicity Studio, select your radio board, select the latest Bluetooth Mesh SDK and create soc-btmesh-light example project for your device.
Copy and replace the attached file (app.c) into your project.
Compile and flash to your radio board.
Open serial console and observe the print statements.
On another radio board, flash any Bluetooth mesh application consisting of the Mesh Proxy service with UUID 0x1828 and provision it.
This functionality was tested with two BGM13P22 radio boards and v1.4.3 of the Silabs Bluetooth Mesh stack.
KBA_BT_0510: Blacklisting Nodes From Bluetooth Mesh Network
Introduction
This article will introduce how to blacklist nodes from a Bluetooth Mesh network and the related APIs when developing with Silicon Labs Bluetooth Mesh SDK. Blacklisting nodes is an important part of the Bluetooth network management, which prevents the "trash-can-attach" risk. It utilizes the key refresh procedure to remove the nodes whose keys are compromised.
There are 2 ways for Bluetooth Mesh network to remove one or more nodes from the network. The first one is via "Config Node Reset" command, the other way is via key refresh, both ways are supported by Silicon Labs Bluetooth Mesh SDK. Table 1 shows a comparison between these 2 ways.
Table 1. Comparison between Config Node Reset and Key Refresh
In addition to blacklist node(s) from the network, the key refresh procedure is also capatible to refresh the application key(s), which results in blacklisting node(s) from some specific group(s) but remaining in the network. One note for refreshing the application keys, it's impossible to refresh only the application keys without refresh the bound network key.
How Key Refresh Works
If you are interested with the detailed information about how the key refresh procedure is designed and how it works, you can look into the chapter 3.10.4 of the Mesh Profile Specification 1.0.
Because the Silabs Bluetooth Mesh SDK has implemented this and packed the procedure to simple API calls, it's OK to just understand the procedure in general, it has 3 phase:
Related APIs In Silabs Bluetooth SDK
Commands
Test Class Commands
The test class commands are for developing and testing purpose, it's NOT recommended to use in the production firmware.
Events
Typical Flow
Below is a pseudo code to demonstrate to blacklist 3 nodes with UUID - uuid1, uuid2 and uuid3.
Example
The project in KBA_BT_0509: Bluetooth Mesh Host Provisioner implements the blacklisting feature, you can use it to try out blacklisting nodes from the network. If you don't have time to go through and understand the whole project, you can just poll out the stuff in blacklisting_devices.c which contains all the blacklisting related code.
KBA_BT_0509: BT Mesh Host Network Manager (Provsioner)
A provisioner plays an important role in the Bluetooth Mesh network, which creates and manages the network by adding, configuring and removing devices into/from the network. This article will provide you a ncp host example which works with the ncp target to act as the provisioner. For more information about the ncp mode and ncp host and target, please go through KBA_BT_1602: NCP Host Implementation and Example.
Prior to this example, we have the SoC mode provisioner example introduced in KBA_BT_0501: BT Mesh embedded provisioner example, it has the full implementation of provisioning and configuring a device into a network and is easier to understand and more suitable for beginners. However, it has below limitations:
Given the above limitations, the host network manager was developed with below ideas in mind.
Capabilities
The host network manager supports below functionalities:
NOTE: Removing a node is different than blacklisting a node from the network. Removing is like to ask the node to leave the network actively - provisioner sends a command to force the node to factory reset itself, while blacklist is passively being blacklisted from the network - provisioner sends packets to the reset of the nodes to migrate to a new network key, see table 1. For more information, you can go through KBA_BT_0510: Blacklisting Nodes From Bluetooth Mesh Network.
Table 1. Comparison between removing and blacklisting
Dependencies
Hardware & SDK
Libraries
This project uses the open source library for parsing the JSON configuration files and glib for the data structures. Users needs to install the libraries properly before using the example.
Architecture
Figure 1. Functional Diagram
The architecture of the host network manager is as shown in figure 1. Below is a brief introduction to each module in this diagram.
Limitation of this design - Only ONE subnet is supported, while multiple subnets feature is supported by the Bluetooth Mesh SDK. It's because the requirements for multiple subnets in practice is not very common yet, so just leave it for future implementation.
Generally, there are 3 parts in the program, CLI, MNG and CFG.
CLI
The command line interface part receives commands from user and pass them to MNG for further processing if needed.
Supported commands
Conventions:
MNG
The MNG part is the core part of the application, which coprate with the other two parts and make sure the network is properly configured according to the configuration files and the received commands.
Features
Simultaneously Provision and Configure Devices
Silicon Labs Bluetooth Mesh SDK supports this feature, as most of the demos uses a 'single thread' way to do it (provision one -> configure one -> provision another -> ...), users may be misled that provision/configure the next device must wait for the compete of the previous one.
To benefit from this, you need to set the 2 fields in the "Memory Configuration" in the NCP target isc file.
Max Prov Sessions - this determines how many devices can be provisioned by the provisioner simultaneously. There is a define #define MAX_PROV_SESSIONS 4 in adding_devices.h of the host project, this value must be equal or less than the setting in the NCP target memory configuration.
Max Foundation Client Cmds - this determines how many nodes can be configured by the provisioner simultaneously. There is a define #define MAX_CONCURRENT_CONFIG_NODES 6 in async_config_client.c of the host project, this value must be equal or less than the setting in the NCP target memory configuration.
Below is a rough time comparison of provisioning and configuring a 50-node network between using 'single thread' way and the asynchronous way. The time itself is meaningless because it heavily depends on the environment, how you configure each node, how many retries for timeouts and interval between retries etc..
Retry
Due to the nature of Bluetooth Mesh technology and the fact that wireless communication is heavily affected by the environments such as packet collision, commands sent to the nodes may be lost. Retry mechanism on the application layer has been implemented to increase the robustness. However, given that retry probably won't solve the error other than timeout or out of memory, so the current implementation will only retry on timeout and out of memory situation. For other errors, it will end the current operation immediately and record the failure status to the node configuration file, so developers could check the error and determine how to deal with it afterwards. It is easy to add any error events to retry, add any specific error event to below the timeout event case in each state callback switch block.
The define symbols in the projconfig.h file determines the maximum retry times for each specific configuration process.
CFG
An example of the configuration files is available in the ${PROJECT_ROOT}/tools/mesh_config/example folder, you could copy it and use it as starting point to configure your network and nodes.
Self Configuration
The content in this file describes how the provisioner should configure itself and how to create the network, see table 4.
Network & Nodes
The content of this file describes how the nodes will be processed, including adding, removing, configuring and blacklisting.
Template
The configuration of one single node might be long, and multiple nodes may have the same configuration just like the concept of group. So the configuration item in the template file provides the configuration for groups. You could add the "Template ID" field to the node and fill it with the specific reference ID of the group. For the case where a specific configuration is both defined in the node field and the group field. The configuration in the node field will be used.
Security
Security is extremely important for your products and the Bluetooth Mesh network. The application aims to provide an example or a starting point for developing this sort of application, so it stores the sensitive data including the network and application keys into the file without encryption. That SHALL NEVER be used when developping the real products. How to securely store the data to the file and make the file to be safe is left for developers respectively.
Secure & Insecure NCP
The provisioner supports both secure and insecure NCP, which are 2 ways of commnicating between the NCP host and target provided by Silicon Labs. With secure NCP, the ncp secure daemon must be running and user needs to feed the socket file path with parameter if it's encrypted to the application. With the insecure NCP, user needs to feed the UART port and baud rate.
Utils
This part can be used by any other parts as utils.
Error Code
The error code design is to provide as much information as possible from the return value. Most of the functions in the program returns a err_t which can either be a 64-bit or 32-bit unsigned value. With separating the bits into different fields, it could contain multiple information pieces. The design in this application divides the unsigned value into 3 fields - error code, line and file information where the error code is generated. There are several functions in the err.h and err.c for generating and parsering the unsigned value. In general, when there is a specific error happens, return the error code surrounded by err(x) macro, when getting a non-zero (not ec_success) unsigned return value, use elog(x) to print the error information to the log file or use eprint(x) which calls printf rather than writting to the log file. Figure 2 shows the elog output.
Figure 2. Error Information
Logging
Logging has the level feature which is inspired from Android logging system. The threshold of the logging is settable via 'loglvlset' command, as a result of which, the logging messages with priority lower than the threshold will not be sent to the logging file. See the table 7 for the logging message types with priorities in descending order.
The logging messages will be written to the file system, the path is specified when initializing the logging.
Logging Format: [Time][File:Line][Level]: Log Message...
[2019-12-12 21:22:33][xxx_source_xxx.c:225][MSG]: Initializing...
Figure 3. Demonstration of Logging
Recommended NCP Target Configuration
The NCP target owns the device database of the network, it's important to set the memory configuration properly so that it can actually store the necessary information of the whole network for the target size. In other words, the memory configuration determines how large your network could be.
Below is an example of setting the memory configuration, in which the network target size is 128. You need to set AT LEAST below items to the memory configuration file, which is in the {PROJECT_NAME}.isc file in your ncp target project.
Furthermore, there are 2 important settings in NVM3 which is the persistent storage solution used in the Bluetooth Mesh stack. You possibly need to increase the settings below if you increase the network target size. For more information, please go through the AN1135: Using Third Generation Non-Volatile Memory (NVM3) Data Storage.
Usage Example for Typical Scenarios
Get It Running
You need to do at least below steps to get it running.
Record Devices Nearby
This could be the first step you use the program. Make sure you have the unprovisioned device placed in the direct radio range to the provisioner and they are sending the unprovisioned device beacon. Then you can do the below steps to record them.
Move Devices from Backlog to Primary Subnet
As mentioned above, the nearby devices recorded by freemode will be added to backlog. You need to cherry pick those you want to add to your network from the backlog to the primary subnet field.
Adding/Configuring Device(s)
Blacklisting Node(s)
Assuming that you have established a network because we cannot blacklist nodes if they are not in the network yet.
Removing Nodes(s)
This procedure is very similar to the last one - Blacklisting Node(s), the only difference is to modify the "RM_Blacklist" Field to "0x10"
Change Configuration to Node(s)
The "Done" field indicates if the node has been configured properly, to change the configuration of nodes, follow the below steps.
Lighting Control
Once you have the network and the nodes configured, the node functionality is stored in the configuration file respectively. Then you can use the CLI commands to control the light status.
Project Repo
Available on Github - https://github.com/fuzhen011/nwmng
KBA_BT_0808: OTA options for NCP-based designs
1. Introduction
This article lays out the different ways of doing device firmware updates (DFU), especially over-the-air updates (OTA), when using NCP Mode in your design. We will use the NCP-target-empty example project as the starting point. Normally the NCP empty example just acts as a bridge between the NCP host and the BLE stack running inside an EFR32 device. In these cases, OTA logic has been included in the NCP-target-empty firmware.
1.1 Adding a bootloader to example projects
When starting with software examples in Simplicity Studio, the project will not contain a bootloader by default. To get the bootloader, either flash an NCP target - Empty demo or create and flash a Gecko Bootloader example project for your part.
1.2 Creating Upgrade Images of your project
SDK examples provide scripts, which generate
.gbl
-files,create_bl_files.bat/.sh
for Windows and Linux/Mac respectively. The images (application.gbl
,full.gbl
and possible secure variants) are created intooutput_gbl
folder.1.3 OTA Client
For methods other than the UART DFU, we will use the Blue Gecko mobile app as the OTA client to perform the upgrade. A guide to using the app can be found here.
2. Firmware Update Methods
2.1 UART DFU
This is probably the most used firmware update method in NCP-mode. A Gecko Bootloader image (.GBL file) containing the new firmware is written to target device using UART and BGAPI binary protocol. The target device needs to be programmed with the Gecko Bootloader as BGAPI UART DFU Bootloader.
The default configuration, suitable for testing with Wireless Starter Kit, is as follows:
The UART DFU process follows these basic steps:
dfu_reset(1)
).DFU boot
event.DFU Flash Set Address
to start the upgrade (set as zero, offsets are calculated automatically)..GBL
) usingDFU flash upload
.DFU upload finish
.dfu_reset(0)
.An NCP host example is provided with the SDK at
<StudioPath>\<version X>\developer\sdks\gecko_sdk_suite\<version>\app\bluetooth\examples_ncp_host\uart_dfu
. For more information about compiling and developing host examples, see AN1042. The host example compiles to an executable, which takes the COM port number, baud rate and full.gbl file as arguments.2.1.1 Testing UART DFU
Create a new NCP-empty-target project for your part. Here a BGM13P22 module is used.
Create a new BGAPI UART DFU Bootloader project for your part.
Flash the
<projectname>-combined.s37
file of the bootloader project to your part first.Build and flash the default NCP-empty-target project to your part. At this point, you should be able to connect to your part with e.g. BGTool to verify that it's running. You should not see any advertisements by default.
Next, we'll add functionality to the NCP-target project, by including the following code in function
local_handle_event
in main.c:This will make the device start advertising with name
"BLE Device"
by default.6.Build the project again and run the
create_bl_files
script.7. Navigate to the
uart-dfu
host example directory mentioned above and compile the host project with e.g.mingw32-make
.8. Copy the
full.gbl
image to the\exe
directory, which now also contains the executable program.9. Run the program from using a command like utility.
uart-dfu.exe <your port> 115200 full.gbl
10. After the upgrade is finished, you should see
"BLE Device"
from, for example, Blue Gecko mobile app Bluetooth Browser. -Success!2.2 AppLoader
The Apploader is a simple application with a minimal Bluetooth stack, that handles the upload process. The Apploader uses the API of the Gecko Bootloader to decode the GBL files and to store the application image in the flash.
For NCP projects, AppLoader should be linked in the project
C/C++ Build->Settings->GNU ARM C Linker->Miscellaneous->${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<partname>/GCC/binapploader.o}
and copied there from the${StudioSdkPath}/protocol/bluetooth/lib/<partname>/GCC/
SDK directory. TheSilicon Labs OTA
service should also be added to your GATT either via the GATT Configurator or gatt.xml file.The standard OTA DFU sequence implemented in the AppLoader goes as follows:
App is running.
Device is reset into DFU mode. In this mode the bootloader will start the Apploader instead of the Application.
The Apploader advertises and waits for a Bluetooth connection.
The AppLoader waits for the OTA start command (
ota_control
characteristic).The Apploader starts receiving the GBL file (using
ota_data
characteristic).The headers of the GBL file are stored in Slot 0 to be parsed.
After parsing the headers, the rest of the GBL file is decoded on-the-fly, and the application is copied right to the application area, overwriting the old application.
The Apploader receives the OTA end command and restarts the device in normal mode.
To implement this and test it, you need to capture the write request to
ota_control
in local event-handling loop to get to step 2. Connection closed event needs to be handled as well.This is implemented in the attached Apploader_OTA_main.c file. The procedure is also described in AN1086 section 3.6.
For testing, flash the modified NCP-empty project to your kit, make another example project for the same part, e.g. SoC-Thermometer and generate the GBL files with the script as described in the beginning sections of this article. Now you should be able to perform OTA with Blue Gecko app and see that the new example is running.
2.3 Application-level OTA
In addition to the basic UART and OTA DFU solutions discussed above, it is possible to implement the firmware update functionality completely in the user application.
The main difference here compared to AppLoader based OTA above is that there is no separate DFU mode and step 2 in the above list is not needed at all. The GBL file is uploaded to the target device under the control of the user application. In this example, the file upload is done using the Silicon Labs proprietary OTA service (as specified in AN1086), but it is possible to use a customer specific service and protocol to handle the file upload.
Some of the benefits of this approach are:
* Sleep and BLE encryption/bonding are not supported by AppLoader to reduce the flash footprint.
An obvious disadvantage of this solution is the requirement to have dedicated flash space available to be used as the download area.
To use this approach, your device needs to be programmed with a suitable Gecko bootloader. When creating the bootloader project select Internal Storage Bootloader (single image on 512kB/1MB device), depending on the size of internal flash in your device.
Gecko bootloader has a key part in the OTA update. After GBL file is uploaded, it is Gecko bootloader that takes care of parsing the GBL file and installing the new firmware. The bootloader is also needed during the OTA file upload.
Gecko bootloader has an application interface exposed through a function table in the bootloader. This means that the user application can call functions implemented in the bootloader, even though the application is running in normal mode. In other words, the bootloader API functions are called from the user application context, but the implementation is in the Gecko bootloader project. As a practical example, the user application can call function
bootloader_writeStorage
to write data into the download area, without even knowing where the download area is physically located.A list of the key bootloader API calls needed to implement OTA update is found in AN1086, Chapter 4. The commands are also shown below in short.
2.3.1 Implementing and testing application-level OTA
Changes made in the NCP-target-empty example:
In GATT Configurator (.isc):
Device Name
characteristicvariable length
checkbox checked and length to 10.user
ota_data
to variable length and length 255ota_data
New files and include paths that need to be added into the project (versus having just binapploader.o linked):
btl_interface.c
andbtl_interface_storage.c
need to be added to the project so that the Gecko bootloader API can be used<studio install>\developer\sdks\gecko_sdk_suite\vX.Y\platform\bootloader\api
"${StudioSdkPath}/platform/bootloader"
"${StudioSdkPath}/platform/bootloader/api"
Changes in
main.c
:The NCP empty example includes a skeleton for adding customized event handling code, it is the function
local_handle_event
. This function is called whenever an event is caught in the main loop. The default implementation is empty, it is merely a placeholder for user code.All the changes in
main.c
are in thelocal_handle_event
(), with some additional includes and definitions added just before this function definition.To support OTA in the NCP firmware, the following event handlers are implemented:
gecko_evt_system_boot_id
gecko_evt_hardware_soft_timer_id
gecko_evt_gatt_server_user_write_request_id
gecko_evt_le_connection_closed_id
See attached example in file app_level_OTA_main.c.
2.3.2 How it works
The implementation follows the same idea that is described in application note AN1086. The boot event handler initializes GPIOs and checks the state of button PB0. If button is pressed at the time of reboot, then the download area is erased by calling
bootloader_eraseStorageSlot(0);
. The boot event also sets the device name dynamically and starts advertising automatically so that OTA can be tested without any NCP host at all.Soft timer is only used for LED blinking. A soft timer is started if the download area is erased. The soft timer handler will then simply toggle the LED pin state.
The user write request event handler is where most of the OTA work is done. Note that the type of
ota_data
characteristic was changed to type user in GATT configurator. Writes toota_control
characteristic will start and terminate the OTA update. Only control values 0 and 3 need to be handled, no other control values are supported by this example.When OTA image data is received (write to
ota_data
), the event handler writes the data directly to the internal flash memory using Gecko bootloader API (bootloader_writeStorage
).When client writes the value 3 to
ota_control
indicating that all the data has been sent, the application verifies the received GBL file by callingbootloader_verifyImage
. GBL file includes checksum which makes it possible to check if the file was corrupted.After successful GBL image upload, the disconnect event triggers the actual firmware update. If the verification was successful, the new GBL image is installed by calling:
bootloader_setImageToBootload(0);
bootloader_rebootAndInstall();
If the image verification failed, the application does not try to install or reboot. Instead, it restarts advertising and includes the error code from the verify function in the device name.
To test the verify feature, you can try OTA update with a corrupted file. The file truncated.gbl is a GBL file from the project that has been intentionally modified so that it does not pass the check (some data has been cut from the end of the file). If you try OTA update with this file, the expected result is that the application will not change and it will restart advertising with name “err XXXX”. You can then erase the download area and try again with a valid GBL file.
2.3.3 How to test it
Preparations:
First, verify the device starts advertising with name “NCP APP 1”. You can also use BGTool to test that the device is responding to BGAPI commands.
To test OTA, you need to manually erase the download area. To do this, keep PB0 pressed and reset the kit. LED1 turns on and after a short delay it starts blinking. The delay is because of the flash erase (~256kB area) which takes time to complete.
The device should now advertise with name “NCP APP 1*”.
Now you can run OTA using the Blue Gecko app. OTA is performed using one single file (fullv1.gbl). In the OTA options, use the partial update which asks you to specify only one GBL file. Select file fullv2.gbl to change the application from version 1 to version 2.
After the OTA upload is complete, you press END button on the mobile app. At this point, the connection is closed and the NCP firmware completes the firmware update. Gecko bootloader is used to install the new image from the download slot.
Installation of the new image takes about 8 seconds and then the device reboots with new firmware installed. At this point, you should see it advertising with a different name “NCP APP 2”.
You can repeat the process and do another update to the original version by using file fullv1.gbl.
2.4 Bluetooth in-place OTA DFU
The download area must not overlap with the user application and therefore the above DFU solution is not applicable to devices or modules based on the EFR32xG1, as they have smaller flash size (256 kB). For EFR32xG1, the Bluetooth in-place OTA DFU Bootloader configuration is used as a default. In this configuration, the upper half of the main flash, normally used to hold the Bluetooth application, is repurposed as a storage area while a Bluetooth stack upgrade is downloaded. The flash layout is illustrated in Fig. 3.1. in AN1086 Section 3.2. For these parts, you can follow the same workflow as described in the Apploader section, but make sure to flash the Bluetooth in-place OTA DFU Bootloader example project (or demo) first.
3. Further reading