Search code examples
bluetooth-lowenergyesp-idfmesh-network

Messaging in ESP_BLE_MESH


I would like to ask for help with my BLE Mesh project.

My task is to create a Mesh network with the following topology:

  • There are about 15 devices that read information from some sensor and once every N seconds send data (just a number from 0 to 300) to the main device. These devices should consume little power.
  • There is ONE master device/gateway that needs to receive data from all other devices on the network and forward those messages to my android app. The master device also has an unlimited power supply.
  • There are Relay devices that help to deliver messages from devices with sensors to the main device. These devices are in fixed locations and have an unlimited power supply.

I decided to build on the Vendor Model from the repository https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/esp_ble_mesh/ble_mesh_vendor_model, because it also distinguishes between the main device - Client and slave devices - Server, and also allows you to automate the provisioning process.

The problem is that the Servers in the Vendor Model example send messages to the Client only in response to a message from that very master inside the example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event, esp_ble_mesh_model_cb_param_t *param) callback:

static void example_ble_mesh_custom_model_cb(esp_ble_mesh_model_cb_event_t event,
                                             esp_ble_mesh_model_cb_param_t *param)
{
    switch (event) {
    case ESP_BLE_MESH_MODEL_OPERATION_EVT:
        if (param->model_operation.opcode == ESP_BLE_MESH_VND_MODEL_OP_SEND) {
            uint16_t tid = *(uint16_t *)param->model_operation.msg;
            ESP_LOGI(TAG, "Recv 0x%06" PRIx32 ", tid 0x%04x", param->model_operation.opcode, tid);
            esp_err_t err = esp_ble_mesh_server_model_send_msg(&vnd_models[0],
                    param->model_operation.ctx, ESP_BLE_MESH_VND_MODEL_OP_STATUS,
                    sizeof(tid), (uint8_t *)&tid);
            if (err) {
                ESP_LOGE(TAG, "Failed to send message 0x%06x", ESP_BLE_MESH_VND_MODEL_OP_STATUS);
            }
        }
        break;
    case ESP_BLE_MESH_MODEL_SEND_COMP_EVT:
        if (param->model_send_comp.err_code) {
            ESP_LOGE(TAG, "Failed to send message 0x%06" PRIx32, param->model_send_comp.opcode);
            break;
        }
        ESP_LOGI(TAG, "Send 0x%06" PRIx32, param->model_send_comp.opcode);
        break;
    default:
        break;
    }
}

while I need Servers to be able to send messages to Client whenever they want.

To do this, I tried to move esp_ble_mesh_server_model_send_msg() into a separate function that would be called every N seconds:

static void send_pulse_data(void* arg) {
    // create message
    esp_err_t err = esp_ble_mesh_server_model_send_msg(&vnd_models[0],
            param->model_operation.ctx, ESP_BLE_MESH_VND_MODEL_OP_STATUS,
            sizeof(message), (uint8_t *)&message);
    if (err) {
        ESP_LOGE(TAG, "Failed to send message 0x%06x", ESP_BLE_MESH_VND_MODEL_OP_STATUS);
    }
}

, but I ran into the fact that in order to send a message to the Client, parameters such as param->model_operation.ctx are needed, which I can’t get anywhere except inside the example_ble_mesh_custom_model_cb callback.

I would like to ask for advice on choosing the right model, on how to send messages from the Servers to the Client for my requirements, on how to receive messages on the Client side and on what functions to use for this. Basically any implementation tips, code snippets or comments would be very helpful to me.

I would also be very grateful if you could answer my questions below:

  1. How to make devices with sensors consume little power? Do I need to explicitly do something for this, or is it enough to disable Relay and send messages once in a limited amount of time?
  2. Is it enough to change ESP_BLE_MESH_RELAY_DISABLED to ESP_BLE_MESH_RELAY_ENABLED to enable Relay?
  3. Do I need to do provisioning every time I use the devices network?

Solution

  • example to send btmesh message :

    void send_to_dimmer(uint8_t payload)
    {
    printf("payload received by send_to_dimmer() 0x%02x", payload);
    esp_ble_mesh_msg_ctx_t ctx = {0};
    esp_err_t err = ESP_OK;
    
    ctx.net_idx = 0x0000;
    ctx.app_idx = 0x0000;
    ctx.addr = 0x0003;   /* dimmer */
    ctx.send_ttl = ESP_BLE_MESH_TTL_DEFAULT;
    ctx.send_rel = true;
    
    err = esp_ble_mesh_server_model_send_msg(&vnd_models[0],&ctx,
     ESP_BLE_MESH_VND_MODEL_OP_SEND, sizeof(payload), &payload);
    if (err) {
        ESP_LOGI(TAG, "Send message to dimmer failed KO");
        return;
    }
    else {ESP_LOGI(TAG, "Message sent to dimmer OK");}
    

    }

    1. How to make devices with sensors consume little power? Do I need to explicitly do something for this, or is it enough to disable Relay and send messages once in a limited amount of time? => I think the biggest problem here is the ESP32 energy consumption. Disabling relay or sending limited amount of message without using esp32 sleep capability might be useless.

    2. Is it enough to change ESP_BLE_MESH_RELAY_DISABLED to ESP_BLE_MESH_RELAY_ENABLED to enable Relay? => normally yes. You can check if relay feature is activated in nRF mesh app for instance (if you used it ot provision your nodes).

    3. Do I need to do provisioning every time I use the devices network? Normally no, in menuconfig, you can find ESP BLE mesh persistent storage option, so that you device will reconnect to network without problem.