Skip to content

Latest commit

 

History

History
215 lines (166 loc) · 10.2 KB

BLE_Mesh_Fast_Prov_Client_Example_Walkthrough.md

File metadata and controls

215 lines (166 loc) · 10.2 KB

1. Introduction

1.1 Demo Function

This demo completes the following functions:

  1. Provisioning an unprovisioned device and change it to a node.
  2. Binding the provisioner's Appkey to its own models.
  3. Sending messages to the node about the Appkey and the fast provisioning information.
  4. Getting the addresses of all the nodes in the fast provisioning network.
  5. Controlling the nodes by their group address.

Note: The demo's functionality is similar to that of the EspBleMesh app.

1.2 Node Composition

This demo has only one element, in which the following four models are implemented:

  • The Configuration Server model is used to represent a mesh network configuration of a device.
  • The Configuration Client model is used to represent an element that can control and monitor the configuration of a node.
  • The Generic OnOff Client model controls a Generic OnOff Server via messages defined by the Generic OnOff model (turning on and off the lights in this demo).
  • The Vendor Client model is used to control the fast_prov_server state, which defines the fast provisioning behavior of a node.

Note: For detailed information about these models, please refer to other BLE Mesh demos.

2. Code Analysis

Code initialization part reference Initializing Bluetooth and BLE Mesh.

2.1 Data Structure

example_prov_info_t is used to define the keys, the address range can be assigned by a node, and the maximum number of nodes supported by the mesh network.

Name Description
net_idx Netkey index value
app_idx AppKey index value
app_key[16] Appkey, which is used throughout the network
node_addr_cnt The maximum number of nodes supported in the mesh network,which serves the same purpose of the Fast provisioning count parameter in the EspBleMesh app
unicast_min Minimum unicast address to be assigned to the nodes in the mesh network
unicast_max Maximum unicast address to be assigned to the nodes in the mesh network
group_addr The group address, which is used to control the on/off state of all nodes in the mesh network, that is said, turning on and off the lights in this demo
match_val[16] The value used by the Fast Provisioning Provisioner to filter the devices to be provisioned
match_len The maximum length of match_val[16]
max_node_num The maximum number of nodes can be provisioned by the client

2.2 Code Flow

The events and APIs in this section are presented in the same order with code execution.

2.2.1 Initialization

2.2.1.1 Set the UUID Filter

The esp_ble_mesh_provisioner_set_dev_uuid_match API is called by the provisioner to set the part of the device UUID to be compared before starting to provision.

/**
 * @brief         This function is called by Provisioner to set the part of the device UUID
 *                to be compared before starting to provision.
 *
 * @param[in]     match_val: Value to be compared with the part of the device UUID.
 * @param[in]     match_len: Length of the compared match value.
 * @param[in]     offset: Offset of the device UUID to be compared (based on zero).
 * @param[in]     prov_after_match: Flag used to indicate whether provisioner should start to provision
 *                                  the device immediately if the part of the UUID matches.
 *
 * @return        ESP_OK on success or error code otherwise.
 *
 */
esp_err_t esp_ble_mesh_provisioner_set_dev_uuid_match(const uint8_t *match_val, uint8_t match_len,
        uint8_t offset, bool prov_after_match);
err = esp_ble_mesh_provisioner_set_dev_uuid_match(match, 0x02, 0x00, false);
if (err != ESP_OK) {
    ESP_LOGE(TAG, "%s: Failed to set matching device UUID", __func__);
    return ESP_FAIL;
}

2.2.1.2 Add local Appkey

The provisioner has no Appkey right after it has been initialized. Therefore, you have to add a local Appkey for the provisioner by calling the esp_ble_mesh_provisioner_add_local_app_key.

err = esp_ble_mesh_provisioner_add_local_app_key(prov_info.app_key, prov_info.net_idx, prov_info.app_idx);
if (err != ESP_OK) {
    ESP_LOGE(TAG, "%s: Failed to add local application key", __func__);
    return ESP_FAIL;
}

Please check the return value of the API calling and the return value of ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_APP_KEY_COMP_EVT, and make sure that the Appkey has been added to this provisioner.

2.2.1.3 Bind Appkey to local model

To control the server model, the client model uses messages to control the server model and these message must be encrypted by the Appkey. To that end, users must bind the Appkey of the provisioner to its local models, which are the Generic OnOff Client model and the Vendor Client model, by calling the esp_ble_mesh_provisioner_add_local_app_key api.

prov_info.app_idx = param->provisioner_add_app_key_comp.app_idx;
err = esp_ble_mesh_provisioner_bind_app_key_to_local_model(PROV_OWN_ADDR, prov_info.app_idx,
                                              ESP_BLE_MESH_MODEL_ID_GEN_ONOFF_CLI, ESP_BLE_MESH_CID_NVAL);
if (err != ESP_OK) {
    ESP_LOGE(TAG, "%s: Failed to bind AppKey with OnOff Client Model", __func__);
    return;
}
err = esp_ble_mesh_provisioner_bind_app_key_to_local_model(PROV_OWN_ADDR, prov_info.app_idx,
                                            ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_CLI, CID_ESP);
if (err != ESP_OK) {
    ESP_LOGE(TAG, "%s: Failed to bind AppKey with Fast Prov Client Model", __func__);
    return;
}

Please check the return value of the API calling and the return value of the ESP_BLE_MESH_PROVISIONER_ADD_LOCAL_APP_KEY_COMP_EVT event, and make sure that the Appkey has been binded to the local models.

2.2.2 Provisioning a device

The unprovisioned devices continuously send the Unprovisioned Device beacon, which contains the value of its UUID.

  • If the UUID matched, a ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT event will be triggered, which will add the unprovisioned device information to the queue of to-be-provisioned devices.

     err = esp_ble_mesh_provisioner_add_unprov_dev(&add_dev, flag);
     if (err != ESP_OK) {
    		ESP_LOGE(TAG, "%s: Failed to start provisioning a device", __func__);
     	return;
     }
    
     if (!reprov) {
    		if (prov_info.max_node_num) {
         	prov_info.max_node_num--;
     }
     }
  • If not, this device will be ignored.

After that, all the devices in the queue will be provisioned automatically.

2.2.3 Sending cache data

Appkey is among the cache required for this node to become a provisioner.

When the provisioning completes, an ESP_BLE_MESH_PROVISIONER_PROV_COMPLETE_EVT event will be triggered, which will add the Appkey to the node's Config Server model by calling the esp_ble_mesh_config_client_set_state API:

common.opcode       = ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD;
common.model        = model;
common.ctx.net_idx  = info->net_idx;
common.ctx.app_idx  = 0x0000; /* not used for config messages */
common.ctx.addr     = info->dst;
common.ctx.send_ttl = 0;
common.msg_timeout  = info->timeout;

return esp_ble_mesh_config_client_set_state(&common, &set);
  • If API calling succeeds, an ESP_BLE_MESH_CFG_CLIENT_SET_STATE_EVT event will be triggered, which sends other cache information (example_fast_prov_info_set_t) to the node's Vendor Server model by calling the example_send_fast_prov_info_set function;
    • If API calling (example_send_fast_prov_info_set) succeeded, a message with an opcode of ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET will be sent, whose acknowledgement (with an opcode of ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS) will further trigger an ESP_BLE_MESH_MODEL_OPERATION_EVT event
       err = example_send_fast_prov_info_set(fast_prov_client.model, &info, &set);
       if (err != ESP_OK) {
       	ESP_LOGE(TAG, "%s: Failed to set Fast Prov Info Set message", __func__);
       return;
       }
    • If API calling (example_send_fast_prov_info_set) times out, an ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT event will be triggered.
  • If API calling times out, an ESP_BLE_MESH_CFG_CLIENT_TIMEOUT_EVT event is triggered.

After that, this node has the ability to provisioning other nodes as a provisioner, and further controls other nodes.

Note: The message with an opcode of ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET contains the group address of all the nodes. When a node receives this message, it will automatically subscribe the Onoff Server model of this address.

2.2.4 Controlling the node

When the ESP_BLE_MESH_MODEL_OPERATION_EVT event is triggered, the provisioner starts a timer.

        ESP_LOG_BUFFER_HEX("fast prov info status", data, len);
#if !defined(CONFIG_BLE_MESH_FAST_PROV)
        prim_prov_addr = ctx->addr;
        k_delayed_work_init(&get_all_node_addr_timer, example_get_all_node_addr);
        k_delayed_work_submit(&get_all_node_addr_timer, GET_ALL_NODE_ADDR_TIMEOUT);
#endif
        break;

After the timers times out, the provisioner starts to get the addresses of all nodes in the mesh network by calling the example_send_fast_prov_all_node_addr_get function, which sends a message with an opcode of ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET.

err = example_send_fast_prov_all_node_addr_get(model, &info);
if (err != ESP_OK) {
    ESP_LOGE(TAG, "%s: Failed to send Fast Prov Node Address Get message", __func__);
    return;
}

After that, the provisioner will receive an acknowledgement, which is a message with an opcode of ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_STATUS, which triggers the ESP_BLE_MESH_MODEL_OPERATION_EVT event.

Then, the provisioner is able to turn on all the nodes (which are lights in this demo) by calling the example_send_generic_onoff_set function using the group address.

example_msg_common_info_t info = {
    .net_idx = node->net_idx,
    .app_idx = node->app_idx,
    .dst = node->group_addr,
    .timeout = 0,
};
err = example_send_generic_onoff_set(cli_model, &info, LED_ON, 0x00, false);
if (err != ESP_OK) {
    ESP_LOGE(TAG, "%s: Failed to send Generic OnOff Set Unack message", __func__);
    return ESP_FAIL;
}