ESP32c6 Nimble-BLE Only send data

Ssg ssg
Posts: 8
Joined: Wed Aug 21, 2024 12:41 am

ESP32c6 Nimble-BLE Only send data

Postby Ssg ssg » Thu Aug 22, 2024 12:19 am

Hi All,
I had many problems developing with esp32c6 module and many BLE examples does not work for esp32c6, mainly if I select "Bluedroid-DualMode" in menuconfig. I did a functional section of my code bellow but I burning my head and I do not know how send data from esp32c6 BT module to android application. I receive the data (buffRxBLE) comming from application but I cannot reply any data as far (buffTxBLE). Unfortunately I could not find any usefully example or tips about that! I think the esp32c6 is under development yet!
Could anyone help me?

Code: Select all

[Codebox=cpp file=Untitled.cpp][/Codebox]#include <assert.h>
#include <string.h>
#include <esp_err.h>
#include "ble_handler.h"
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "esp_log.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "sdkconfig.h"

#define BLE_DEBUG
#define BLE_TAG "ble_handler"

#ifdef BLE_DEBUG
#define BLE_DEBUGF(BLE_TAG, format, ...) ESP_LOGI(BLE_TAG, format, ##__VA_ARGS__)
#else
#define BLE_DEBUGF(BLE_TAG, format, ...)
#endif /* BLE_DEBUG */

#define DEVICE_NAME "ESP32-C6"

char *TAG = "BLE-Server";
uint8_t ble_addr_type;
void ble_app_advertise(void);
extern char * buffRxBLE;                                     // buffer reception
extern char *buffTxBLE;                                          // pointer for tx buffer

// data sent from remote partner/app to ESP32
static int device_write(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg){
    buffRxBLE=0;
    buffRxBLE = (char *)ctxt->om->om_data;
    printf("Data sent from bufferRx: %.*s\n", ctxt->om->om_len, ctxt->om->om_data);
    vTaskDelay(5);
    return 0;
}

// data sent from ESP32 to remote partner/app
static int device_read(uint16_t con_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg){
    printf("Data receipt bufferTx.........: %s\n", buffTxBLE);
    os_mbuf_append(ctxt->om, buffTxBLE, strlen(buffTxBLE));
    vTaskDelay(10);
    return 0;
}

// Array of pointers to other service definitions
// UUID - Universal Unique Identifier
static const struct ble_gatt_svc_def gatt_svcs[] = {
    {.type = BLE_GATT_SVC_TYPE_PRIMARY,
     .uuid = BLE_UUID16_DECLARE(0xFFE0),                 // Define UUID for device type
     .characteristics = (struct ble_gatt_chr_def[]){
         {.uuid = BLE_UUID16_DECLARE(0xFFE1),           // Define UUID for writing
//         .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE_NO_RSP,
          .flags = BLE_GATT_CHR_F_WRITE, // | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE_NO_RSP,
          .access_cb = device_write},
         {.uuid = BLE_UUID16_DECLARE(0xFFE2),           // Define UUID for reading
          .flags = BLE_GATT_CHR_F_READ,
//          .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_WRITE_NO_RSP,
          .access_cb = ble_svc_gatt_srv_sup_feat_access},
         {0}}},
    {0}};

// BLE event handling
static int ble_gap_event(struct ble_gap_event *event, void *arg){
    switch (event->type){
    // If connected
    case BLE_GAP_EVENT_CONNECT:
        ESP_LOGI("GAP", "BLE GAP APP CONNECTION %s", event->connect.status == 0 ? "OK!" : "FAIL!");
        if (event->connect.status != 0)
            ble_app_advertise();
        break;
    // Advertise again after completion of the event
    case BLE_GAP_EVENT_DISCONNECT:
        ESP_LOGI("GAP", "BLE GAP CLIENT DISC");
        ble_app_advertise();
        break;
    case BLE_GAP_EVENT_ADV_COMPLETE:
        ESP_LOGI("GAP", "BLE GAP EVENT OK");
        ble_app_advertise();
        break;
    default:
        break;
    }
    return 0;
}

// BLE
void ble_app_advertise(void){
    // GAP (Generic Access Profile)
    struct ble_hs_adv_fields fields;
    const char *device_name;
    memset(&fields, 0, sizeof(fields));
    fields.flags = BLE_HS_ADV_F_DISC_GEN |              // show BLE
                   BLE_HS_ADV_F_BREDR_UNSUP;            // show in mobile devices
    device_name = ble_svc_gap_device_name();
    fields.name = (uint8_t *)device_name;
    fields.name_len = strlen(device_name);
    fields.name_is_complete = 1;
    ble_gap_adv_set_fields(&fields);
    // GAP conectivity
    struct ble_gap_adv_params adv_params;
    memset(&adv_params, 0, sizeof(adv_params));
    // NON: non 3.C.9.3.2   DIR: directed 3.C.9.3.3) UND: undirected 3.C.9.3.4
    adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
    //NON: non 3.C.9.2.2    LTD: limited 3.C.9.2.3   GEN: general 3.C.9.2.4)
    adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
    ble_gap_adv_start(ble_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_gap_event, NULL);
}

// Application
void ble_app_on_sync(void){
    ble_hs_id_infer_auto(0, &ble_addr_type);    // Determines the best address type automatically
    ble_app_advertise();                        // Define the BLE connection
}

// Task
void host_task(void *param){
    nimble_port_run();                          // This function will return only when nimble_port_stop() is executed
}

//
esp_err_t esp32_ble_initialize(){
    nvs_flash_init();                          // 1 - NVS flash
    nimble_port_init();                        // 2 - host stack
    ble_svc_gap_device_name_set(DEVICE_NAME);    // 3 - NimBLE server
    ble_svc_gap_init();                        // 4 - NimBLE gap service
    ble_svc_gatt_init();                       // 5 - NimBLE gatt service
    ble_gatts_count_cfg(gatt_svcs);            // 6 - NimBLE config gatt services
    ble_gatts_add_svcs(gatt_svcs);             // 7 - NimBLE queues gatt services
    ble_hs_cfg.sync_cb = ble_app_on_sync;      // 8 - Ini app
    nimble_port_freertos_init(host_task);      // 9 - Run thread
    return ESP_OK;
}

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32c6 Nimble-BLE Only send data

Postby MicroController » Thu Aug 22, 2024 1:43 pm

Like all newer ESP32s, the C6 supports only BLE but not "classic" Bluetooth.

With NimBLE, you only have one callback function ("access_cb") per attribute ("device_write" in your case).
Inside this function, you need to check the value of ble_gatt_access_ctxt::op to see if a read (BLE_GATT_ACCESS_OP_READ_CHR) or a write (BLE_GATT_ACCESS_OP_WRITE_CHR) needs to be handled and react accordingly, see https://mynewt.apache.org/latest/networ ... ccess_ctxt

You can find an example e.g. here.

Ssg ssg
Posts: 8
Joined: Wed Aug 21, 2024 12:41 am

Re: ESP32c6 Nimble-BLE Only send data

Postby Ssg ssg » Fri Aug 23, 2024 11:26 pm

Thanks for your reply, but where in example is BLE_GATT_ACCESS_OP_READ_CHR? I think my code is almost ready, I need just do the advertising and read the reception buffer...
Obs: Even upgrading to esp-idf V5.3 this example did not compilate to me...

Ssg ssg
Posts: 8
Joined: Wed Aug 21, 2024 12:41 am

Re: ESP32c6 Nimble-BLE Only send data

Postby Ssg ssg » Sat Aug 24, 2024 6:50 pm

Well, the example does not compilate to me :cry:
I only need put my data inside buffer and send it...

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32c6 Nimble-BLE Only send data

Postby MicroController » Sun Aug 25, 2024 8:06 am

Ssg ssg wrote:
Fri Aug 23, 2024 11:26 pm
where in example is BLE_GATT_ACCESS_OP_READ_CHR?
It's right here.
Obs: Even upgrading to esp-idf V5.3 this example did not compilate to me...
Seems like you have a problem in your project setup.
How did you create & set up the example project?

Ssg ssg
Posts: 8
Joined: Wed Aug 21, 2024 12:41 am

Re: ESP32c6 Nimble-BLE Only send data

Postby Ssg ssg » Mon Aug 26, 2024 4:06 pm

Hi MicroController, I check and recheck my setup, using nimble-only and seems to be ok all updated (esp-idf V-5.3.0, python3)...
I copy the example suggested for you, create a new project with esp-idf in terminal mode, put everything inside and configurate new options in menuconfig (just works and enable extended adv) but unfortunately it stops with that error: "[2/4] failed bleprph.elf and ninja" terminated with exit code: 1" on final with not suggestion for correction...
In my code above I do not use BLE_GATT_ACCESS_OP_READ_CHR but using BLE_GATT_CHR_F_READ that works similar (I changed the .access_cb = ble_svc_gatt_srv_sup_feat_access for device_read), it means the with nRFConnect application I can send and receive data but the initiative always comes/commanded from application. I need now only send data from ESP to my application with ESP initiative. I tried populate the os_mbuf in specific function but crashs the system with error "panic'ed load access fault exception was unhandled"...
I'm thinking and seeing something to add a "advertising" after load my buffer but no usefully example up to now :cry:
Last edited by Ssg ssg on Mon Aug 26, 2024 4:33 pm, edited 2 times in total.

MicroController
Posts: 1734
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32c6 Nimble-BLE Only send data

Postby MicroController » Mon Aug 26, 2024 4:18 pm

With BLE, one device provides services and attributes, while the other device can issue read and write commands.
If the device providing the service wants to proactively send data without an explicit read command from the other side, it can do so using BLE notifications or indications. It can also broadcast some custom data via advertisements.

Ssg ssg
Posts: 8
Joined: Wed Aug 21, 2024 12:41 am

Re: ESP32c6 Nimble-BLE Only send data

Postby Ssg ssg » Mon Aug 26, 2024 4:29 pm

MicroController,
Do you have any example?
(your knowledgment is my salvation... :D )

Ssg ssg
Posts: 8
Joined: Wed Aug 21, 2024 12:41 am

Re: ESP32c6 Nimble-BLE Only send data

Postby Ssg ssg » Mon Sep 30, 2024 10:10 pm

Well, after many days speding my precious time I found one solution for indicate procedure. First of all I did a lot of debug points in GATT read and write chr, so I got conn_handle=1 and attrib_handle=16 and I put my data inside buffer to "om":
  1. if (attr_handle == chr_val_handle) {
  2. /* Update access buffer value */
  3. rc = os_mbuf_append(ctxt->om, bufTx, strlen(bufTx));
  4. printf("Characteristic write to APP--------------------: conn_read:%d attr_handle:%d\n", conn_handle, attr_handle);
  5. return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
  6. }
Finally send the data with:
  1. ble_gatts_indicate_custom(1, 16, om);
and it works, my data goes ahead...

Thank you so much for Mr. Zheng from Espressif for open my mind!
Samy

Who is online

Users browsing this forum: No registered users and 81 guests