Users could refer to the sections for quick answer to their questions. This document will be updated based on the feedback collected via various channels.
.._ble-mesh-faq-provisioner-development:
1. Provisioner Development
--------------------------
Generally, a Provisioner is used to provision unprovisioned devices and form a mesh network. And after provisioning, roles of the unprovisioned devices will be changed to those of a node.
There are two phases for a device to join ESP-BLE-MESH network via a Provisioner, namely, provisioning and configuration.
- The phase of provisioning is to assign unicast address, add NetKey and etc. to a device. By provisioning, the device joins the ESP-BLE-MESH network and its role is changed from an unprovisioned device to a node.
- The phase of configuration is to add AppKeys to the node and bind AppKeys to corresponding models. And some items are optional during configuration, including adding subscription addresses to the node, set publication information, etc. By configuration, the node can actually transmit messages to a Provisioner and receive messages from it.
- NetKey is used for encryption of messages in Network Layer. Nodes with the same NetKey are assumed to be in the same subnet while those with different NetKeys cannot communicate with each other.
- AppKey is used for encryption of messages in Upper Transport Layer. If client model and server model are bound to different AppKeys, the communication cannot be achieved.
The value of :code:`prov_unicast_addr` in :cpp:type:`esp_ble_mesh_prov_t` is used to set the unicast address of Provisioner, it can be set only once during initialization and cannot be changed afterwards.
The unicast address of Provisioner can be set only once during initialization and cannot be changed afterwards. In theory, it can serve as the destination address of the node-reporting-status message, provided that the unicast address of the Provisioner is known by nodes. Nodes can know the unicast address of Provisioner during configuration since Provisioner sends messages to them with its unicast address used as the source address.
Subscription address can also be used. Provisioner subscribes to a group address or virtual address, and nodes send messages to the subscription address.
The value of :code:`prov_start_address` in :cpp:type:`esp_ble_mesh_prov_t` is used to set the starting address when the Provisioner provisions unprovisioned devices, i.e., the unicast address of the node it firstly provisioned. It can be set only once during initialization and cannot be changed afterwards.
The value of :code:`prov_attention` in :cpp:type:`esp_ble_mesh_prov_t` is used by Provisioner set to unprovisioned device during provisioning. It can be set only once during initialization and cannot be changed afterwards. When the unprovisioned device is joining the mesh network, it can display in a specific way like flashing light to notify Provisioner that it is being provisioned.
- Provisioner will assign an unicast address for the primary element of the node, and unicast address of the remaining elements are incremented one by one.
- For example: If an unprovisioned device has three elements, i.e., the primary element, the second element and the third element. After provisioning, the primary element address of the node is 0x0002 while the second element address is 0x0003, and the third element address is 0x0004.
- Provisioner can get the Composition Data of nodes using the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state` with :code:`comp_data_get` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_get_state_t` set properly.
- Users can refer to the following code to parse the Composition Data:
Provisioner do the following configuration by calling the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state`.
- Add AppKey to nodes with :code:`app_key_add` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
- Add subscription address to the models of nodes with :code:`model_sub_add` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
- Set publication information to the models of nodes with :code:`model_pub_set` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
model = esp_ble_mesh_find_sig_model(element, model_id);
if (!model) {
continue;
}
for (j = 0; j < ARRAY_SIZE(model->groups); j++) {
if (model->groups[j] == group_addr) {
break;
}
}
if (j != ARRAY_SIZE(model->groups)) {
ESP_LOGW(TAG, "%s: Group address already exists, element index: %d", __func__, i);
continue;
}
for (j = 0; j < ARRAY_SIZE(model->groups); j++) {
if (model->groups[j] == ESP_BLE_MESH_ADDR_UNASSIGNED) {
model->groups[j] = group_addr;
break;
}
}
if (j == ARRAY_SIZE(model->groups)) {
ESP_LOGE(TAG, "%s: Model is full of group addresses, element index: %d", __func__, i);
}
}
return ESP_OK;
}
..note::
When the NVS storage of the node is enabled, group address added and AppKey bound by this method will not be saved in the NVS when the device is powered off currently. These configuration information can only be saved if they are configured by Configuration Client Model.
Generally there are two approaches to implement group control in ESP-BLE-MESH network, group address approach and virtual address approach. And supposing there are 10 devices, i.e., five devices with blue lights and five devices with red lights.
- Method 1: 5 blue lights can subscribe to a group address, 5 red lights subscribe to another one. By sending messages to different group addresses, Provisioner can realize group control.
- Method 2: 5 blue lights can subscribe to a virtual address, 5 red lights subscribe to another one. By sending messages to different virtual addresses, Provisioner can realize group control.
Provisioner can add multiple NetKeys to nodes during configuration, and nodes sharing the same NetKey belong to the same subnet. Provisioner can communicate with nodes on different subnets by using different NetKeys.
Node offline is usually defined as: the condition that the node cannot be properly communicated with other nodes in the mesh network due to power failure or some other reasons.
There is no connection between nodes and nodes in the ESP-BLE-MESH network. They communicate with each other through advertising channels.
An example is given here to show how to detect a node is offline by Provisioner.
- The node can periodically send heartbeat messages to Provisioner. And if Provisioner failed to receive heartbeat messages in a certain period, the node is considered to be offline.
..note::
The heartbeat message should be designed into a single package (less than 11 bytes), so the transmission and reception of it can be more efficient.
- Provisioner updates the NetKey of nodes using the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state` with :code:`net_key_update` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
- Provisioner updates the AppKey of nodes using the :ref:`Configuration Client Model <ble-mesh-terminology-foundation-models>` API :cpp:func:`esp_ble_mesh_config_client_set_state` with :code:`app_key_update` in the parameter :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` set properly.
ESP-BLE-MESH implements several functions related to basic node management in the example, such as :cpp:func:`esp_ble_mesh_store_node_info`. And ESP-BLE-MESH also provides the API :cpp:func:`esp_ble_mesh_provisioner_set_node_name` which can be used to set the node's local name and the API :cpp:func:`esp_ble_mesh_provisioner_get_node_name` which can be used to get the node's local name.
ESP-BLE-MESH supports all SIG-defined client models. Provisioner can use these client models to control the server models of nodes. And the client models are divided into 6 categories with each category has the corresponding functions.
- Configuration Client Model
- The API :cpp:func:`esp_ble_mesh_config_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_cfg_client_get_state_t` values of Configuration Server Model.
- The API :cpp:func:`esp_ble_mesh_config_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_cfg_client_set_state_t` values of Configuration Server Model.
- Health Client Model
- The API :cpp:func:`esp_ble_mesh_health_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_health_client_get_state_t` values of Health Server Model.
- The API :cpp:func:`esp_ble_mesh_health_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_health_client_set_state_t` values of Health Server Model.
- Generic Client Models
- The API :cpp:func:`esp_ble_mesh_generic_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_generic_client_get_state_t` values of Generic Server Models.
- The API :cpp:func:`esp_ble_mesh_generic_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_generic_client_set_state_t` values of Generic Server Models.
- Lighting Client Models
- The API :cpp:func:`esp_ble_mesh_light_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_light_client_get_state_t` values of Lighting Server Models.
- The API :cpp:func:`esp_ble_mesh_light_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_light_client_set_state_t` values of Lighting Server Models.
- Sensor Client Models
- The API :cpp:func:`esp_ble_mesh_sensor_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_sensor_client_get_state_t` values of Sensor Server Model.
- The API :cpp:func:`esp_ble_mesh_sensor_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_sensor_client_set_state_t` values of Sensor Server Model.
- Time and Scenes Client Models
- The API :cpp:func:`esp_ble_mesh_time_scene_client_get_state` can be used to get the :cpp:type:`esp_ble_mesh_time_scene_client_get_state_t` values of Time and Scenes Server Models.
- The API :cpp:func:`esp_ble_mesh_time_scene_client_set_state` can be used to set the :cpp:type:`esp_ble_mesh_time_scene_client_set_state_t` values of Time and Scenes Server Models.
- In ESP-BLE-MESH, nodes are all composed of a series of models with each model implements some functions of the node.
- Model has two types, client model and server model. Client model can get and set the states of server model.
- Model can also be divided into SIG model and vendor model. All behaviors of SIG models are officially defined while behaviors of vendor models are defined by users.
Acknowledged message is needed if users want to transmit messages without packet loss. The default time to wait for corresponding response is set in :ref:`CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT`. If the sender waits for the response until the timer expires, the corresponding timeout event would be triggered.
Response timeout can be set in the API :cpp:func:`esp_ble_mesh_client_model_send_msg`. The default value (4 seconds) would be applied if the parameter :code:`msg_timeout` is set to **0**.
For client models, users can use the API :cpp:func:`esp_ble_mesh_client_model_send_msg` with the parameter :code:`need_rsp` set to :code:`false` to send unacknowledged messages.
For server models, the messages sent by using the API :cpp:func:`esp_ble_mesh_server_model_send_msg` are always unacknowledged messages.
Messages sent by calling the API :cpp:func:`esp_ble_mesh_client_model_send_msg` or :cpp:func:`esp_ble_mesh_server_model_send_msg` will be sent in the duration determined by the Network Transmit state.
Messages published by calling the API :cpp:func:`esp_ble_mesh_model_publish` will be published determined by the Model Publication state. And the publication of messages is generally periodic or with a fixed number of counts. The publication period and publication count are controlled by the Model Publication state, and can be configured through Configuration Client Model.
The total payload length (which can be set by users) of unsegmented message is 11 octets, so if the opcode of the message is 2 octets, then the message can carry 9-octets of valid information. For vendor messages, due to the 3-octets opcode, the remaining payload length is 8 octets.
If the unprovisioned device is expected to be provisioned by a phone, then it should enable the Proxy feature since almost all the phones do not support sending ESP-BLE-MESH packets through advertising bearer currently. And after the unprovisioned device is provisioned successfully and becoming a Proxy node, it will communicate with the phone using GATT bearer and using advertising bearer to communicate with other nodes in the mesh network.
The Proxy filter is used to reduce the number of Network PDUs exchanged between a Proxy Client (e.g., the phone) and a Proxy Server (e.g., the node). And with the Proxy filter, Proxy Client can explicitly request to receive only mesh messages with certain destination addresses from Proxy Server.
2.13 If a Message Is Segmented into Several Segments, Should the Other Relay Nodes Just Relay When One of These Segments Is Received or Wait Until the Message Is Received Completely?
- When the radio is turned on for listening, the device is consuming energy. When low power feature of the node is enabled, it will turn off its radio in the most of the time.
- And cooperation is needed between low power node and friend node, thus low power node can receive messages at an appropriate or lower frequency without the need to keep listening.
- When there are some new messages for low power node, its friend node will store the messages for it. And low power node can poll friend nodes to see if there are new messages at a fixed interval.
One possible application scenario for transmitting information between nodes is that spray nodes would be triggered once smoke alarm detected high smoke concentration. There are two approaches in implementation.
- Approach 1 is that spray node subscribes to a group address. When smoke alarm detects high smoke concentration, it will publish a message whose destination address is the group address which has been subscribed by spray node.
- Approach 2 is that Provisioner can configure the unicast address of spray node to the smoke alarm. When high smoke concentration is detected, smoke alarm can use send messages to the spray node with the spray node's unicast address as the destination address.
- Situation 1: nodes only communicate within the mesh network. In this situation, no gateway is need. ESP-BLE-MESH network is a flooded network, messages in the network have no fixed paths, and nodes can communicate with each other freely.
- Situation 2: if users want to control the nodes remotely, for example turn on some nodes before getting home, then a gateway is needed.
The :doc:`ESP32-DevKitC <../../hw-reference/esp32/get-started-devkitc>` board without PSRAM can run properly but the throughput of it is low since it has no PSRAM. When Bluetooth and Wi-Fi coexist, the throughput of ESP32-DevKitC with PSRAM can be stabilized to more than 1 Mbps.
Normally when they are several unprovisioned devices, users can provision them one by one. But when it comes to a large number of unprovisioned devices (e.g., 100), provisioning them one by one will take huge amount of time. With fast provisioning, users can provision 100 unprovisioned devices in about 50 seconds.
After the App provisioned one Proxy node, it will disconnect from the App during fast provisioning, and reconnect with the App when all the nodes are provisioned.
Each time after a fast provisioning process, and before starting a new one, the node addresses in the App should be cleared, otherwise the number of the node address will be incorrect.
4.5 When will Configuration Client Model of the node running :example:`fast_prov_server <bluetooth/esp_ble_mesh/fast_provisioning/fast_prov_server>` example start to work?
When the node transmits a segmented message, and due to some reasons, the receiver does not receive the complete message. Then the node will retransmit the message. When the retransmission count reaches the maximum number, which is 4 currently, then this warning will appear.
When the node receives a message, it will compare the message with the ones stored in the network cache. If the same has been found in the cache, which means it has been received before, then the message will be dropped.
When the node does not receive all the segments of a segmented message during a certain period (e.g., 10 seconds), then the Incomplete timer will expire and this warning will appear.
When the node has no space for receiving new segmented message, this warning will appear. Users can make the space larger through the configuration :ref:`CONFIG_BLE_MESH_RX_SEG_MSG_COUNT`.
This error means client model of the node has transmitted a message to the target node and now is waiting for a response, users can not send messages to the same node with the same unicast address. After the corresponding response is received or timer is expired, then another message can be sent.
- The API :cpp:func:`esp_ble_mesh_register_prov_callback` is used to register callback function used to handle provisioning and networking related events.
- The API :cpp:func:`esp_ble_mesh_register_config_client_callback` is used to register callback function used to handle Configuration Client Model related events.
- The API :cpp:func:`esp_ble_mesh_register_config_server_callback` is used to register callback function used to handle Configuration Server Model related events.
- The API :cpp:func:`esp_ble_mesh_register_health_client_callback` is used to register callback function used to handle Health Client Model related events.
- The API :cpp:func:`esp_ble_mesh_register_health_server_callback` is used to register callback function used to handle Health Server Model related events.
- The API :cpp:func:`esp_ble_mesh_register_generic_client_callback` is used to register callback function used to handle Generic Client Models related events.
- The API :cpp:func:`esp_ble_mesh_register_light_client_callback` is used to register callback function used to handle Lighting Client Models related events.
- The API :cpp:func:`esp_ble_mesh_register_sensor_client_callback` is used to register callback function used to handle Sensor Client Model related events.
- The API :cpp:func:`esp_ble_mesh_register_time_scene_client_callback` is used to register callback function used to handle Time and Scenes Client Models related events.
- The API :cpp:func:`esp_ble_mesh_register_custom_model_callback` is used to register callback function used to handle vendor model and unrealized server models related events.