Code initialization part reference [Initializing Bluetooth and BLE Mesh](../../../ble_mesh_wifi_coexist/tutorial/BLE_Mesh_WiFi_Coexist_Example_Walkthrough.md).
Among which, there are four roles in this demo (`primary_role`):
* Phone - Top Provisioner
* The device that has been provisioned by Phone - Primary Provisioner
* Devices that have been provisioned and changed to the role of a provisioner - Temporary Provisioner
* Devices that have been provisioned but not changed to the role of a provisioner - Node
#### 2.1.2 Provisioner Address Management
The provisioner address management is used to assign a unicast address to each node, so as to prevent address conflicts by allocating address in an equally manner. Each provisioner has its own address range and a maximum number of the nodes it can provisioned. The provisioner will allocate a subset of its address range to the nodes it has provisioned.
Example: A top provisioner's address range is 0 to 100 and the maximum number of nodes it can provisioned is 5. The provisioner address management will assign subsets of address range to these 5 nodes, which are 1 to 20, 21 to 40, 41 to 60, 61 to 80 and 81 to 100.
The variables that are related to the address management are described in the following table:
The cache data is required, so a node can change its role to become a provisioner. During this process, the `esp_ble_mesh_set_fast_prov_info` and `esp_ble_mesh_set_fast_prov_action` APIs are called.
The node's cache data, which are described in the following table, is sent by the provisioner.
| `prim_prov_addr` |Unicast address of Primary Provisioner |
| `match_val[16]` |Match value to be compared with unprovisioned device UUID |
| `match_len` | Length of match value to be compared |
| `max_node_num` | The maximum number of devices can be provisioned by the Provisioner |
| `prov_node_cnt` | Number of self-provisioned nodes |
| `app_idx` | AppKey index of the application key added by other Provisioner |
| `top_address` | Address of the device(e.g. phone) which triggers fast provisioning |
#### 2.1.4 Provisioner Timer
There are two timers in this demo, which are:
1.`gatt_proxy_enable_timer` is used to enable Mesh GATT Proxy functionality.
* The timer starts or resets and starts when a Temporary Provisioner provisions an unprovisioned device.
* The Temporary Provisioner will send a message (Address information) to the Primary Provisioner.
2.`disable_fast_prov_timer` is used to disable the provisioning capabilities.
* The node starts the timer when it receives a **Generic OnOff Get/Set/Set Unack** message sent by the EspBleMesh app. The group address should be used if you want to disable the provisioning capabilities of all nodes.
The variables that are related to these two timers are described below:
| `disable_fast_prov_timer` |Used to disable fast provisioning|
| `gatt_proxy_enable_timer` |Used to enable Mesh GATT Proxy functionality|
### 2.2 Model Definition
#### 2.2.1 Vendor Server Model
The **Vendor Server** Model implements the node's `fast_prov_server` state, which has been covered in the previous section.
```c
example_fast_prov_server_t fast_prov_server = {
.primary_role = false,
.max_node_num = 6,
.prov_node_cnt = 0x0,
.unicast_min = ESP_BLE_MESH_ADDR_UNASSIGNED,
.unicast_max = ESP_BLE_MESH_ADDR_UNASSIGNED,
.unicast_cur = ESP_BLE_MESH_ADDR_UNASSIGNED,
.unicast_step = 0x0,
.flags = 0x0,
.iv_index = 0x0,
.net_idx = ESP_BLE_MESH_KEY_UNUSED,
.app_idx = ESP_BLE_MESH_KEY_UNUSED,
.group_addr = ESP_BLE_MESH_ADDR_UNASSIGNED,
.prim_prov_addr = ESP_BLE_MESH_ADDR_UNASSIGNED,
.match_len = 0x0,
.pend_act = FAST_PROV_ACT_NONE,
.state = STATE_IDLE,
};
```
The `fast_prov_srv_op` is used to register the minimum length of messages. For example, the minimum length of the `ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET` message is registered as 3 octets.
The `example_fast_prov_server_init` function is used to register the callback function triggered when the timers timeout, and initializes the Model-related variables in the data struct.
ESP_LOGE(TAG, "%s: Failed to initialize fast prov server model", __func__);
return err;
}
```
The `fast_prov_server` struct represents the Vendor server's states. The `CID_ESP` and `ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_SRV` constants, which consist of the vendor server Model's Model id `ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_SRV`, are used to identity the Vendor server Model.
Example: The **Vendor Client** Model sends message with an opcode of `ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET`, which requires the **Vendor Server** Model to respond with a message with an opcode of `ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS`. After that, the **Vendor Client** Model times out if it receives no corresponding acknowledgement.
Note that you can also use the code below if you don't want the **Vendor Client** Model to wait for acknowledgement from the server Model, which means the client Model will never time out.
The `esp_ble_mesh_client_model_init` API is used to register the callback function triggered when the timers timeout, and initializes the Model-related variables in the data struct.
ESP_LOGE(TAG, "%s: Failed to initialize fast prov client Model", __func__);
return err;
}
```
The `CID_ESP` and `ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_CLI` constants, which consist of the vendor client Model's Model id `ESP_BLE_MESH_VND_MODEL_ID_FAST_PROV_CLI`, are used to identity the Vendor client Model.
|Function| This message contains all the information as a Provisioner |Checks each field of the Provisioner information and set the corresponding flag bit. The returned status is variable.|
|Function|Top Provisioner gets the address of all nodes obtained from Primary Provisioner. | Returns the address of all nodes, but does not contain its own. |
| ESP_BLE_MESH_MODEL_OPERATION_EVT|ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET | This event is triggered when the **Generic Onoff Server** model receives the `ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET` message |
| ESP_BLE_MESH_MODEL_OPERATION_EVT|ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK| This event is triggered when the **Generic Onoff Server** model receives the `ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK` message. |
| ESP_BLE_MESH_MODEL_OPERATION_EVT | ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET | This event is triggered when the **Vendor Server** model receives the `ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET` message.|
| ESP_BLE_MESH_MODEL_OPERATION_EVT | ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR | This event is triggered when the **Vendor Server** model receives the `ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR` message.|
| ESP_BLE_MESH_MODEL_OPERATION_EVT | ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET | This event is triggered when the **Vendor Server** model receives the `ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_GET` message.|
|ESP_BLE_MESH_SET_FAST_PROV_INFO_COMP_EVT| NA| This event is triggered when the `esp_ble_mesh_set_fast_prov_info` API is called. |
|ESP_BLE_MESH_SET_FAST_PROV_ACTION_COMP_EVT| NA| This event is triggered when the `esp_ble_mesh_set_fast_prov_action` API is called. |
|ESP_BLE_MESH_CFG_CLIENT_SET_STATE_EVT|ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD|This event is triggered when the **Configuration Server** model receives and further triggers an API calling to send `ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_SET` message. |
|ESP_BLE_MESH_CFG_CLIENT_TIMEOUT_EVT|ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD|This event is triggered when the API `example_send_config_appkey_add` times out.|
| ESP_BLE_MESH_MODEL_OPERATION_EVT | ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS | This event is triggered when the **Vendor Client** model receives the `ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_INFO_STATUS` message.|
| ESP_BLE_MESH_MODEL_OPERATION_EVT | ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_STATUS | This event is triggered when the **Vendor Client** model receives the `ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NET_KEY_STATUS` message.|
| ESP_BLE_MESH_MODEL_OPERATION_EVT | ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_ACK | This event is triggered when the **Vendor Client** model receives the `ESP_BLE_MESH_VND_MODEL_OP_FAST_PROV_NODE_ADDR_ACK` message |
| ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT | client_send_timeout.opcode | This event is triggered when the API `esp_ble_mesh_client_model_send_msg` times out.|
### 2.5 Message Sending
#### 2.5.1 The Vendor Client sends messages
The Vendor Client Model calls the `esp_ble_mesh_client_model_send_msg` API to send messages to the Vendor Server Model.
The **Vendor Server** Model calls the `esp_ble_mesh_model_publish` API to publish messages. Only the Models that have subscribed to this destination address receive the published messages.