uploaded 1 day ago
A lightweight ESP32 BLE component for fast, bidirectional communication

readme

# ble_bidi_fast

A lightweight ESP32 Bluetooth Low Energy (BLE) component for fast, bidirectional communication.

## Overview

`ble_bidi_fast` is a reusable ESP32 BLE component designed for efficient, bidirectional data transfer between an ESP32 device and a BLE client (e.g., a mobile app). It provides:

- **Configurable Setup**: Customizable device name, 128-bit Service UUID, TX Characteristic UUID, and RX Characteristic UUID.
- **Bidirectional Data Transfer**: Transmit data from the ESP32 to the client (via TX Characteristic) and receive data from the client (via RX Characteristic) with a user-defined callback.
- **Optimized Performance**: Fast communication with advertising intervals of 32ms–64ms and connection intervals of 7.5ms–15ms.
- **Error Handling**: Robust error checking for initialization, data transmission, and GATT/GAP operations.

This component is ideal for low-latency applications requiring compact binary data exchange over BLE.

## Features

- **Bidirectional Communication**: Supports transmitting data to the client (Notify property on TX Characteristic) and receiving data from the client (Write and Write No Response properties on RX Characteristic).
- **Customizable Configuration**: Define device name, UUIDs, and a callback for received data via a configuration structure.
- **Compact Data**: Handles binary data for both TX and RX operations.
- **High Performance**: Optimized for low latency with short advertising and connection intervals.
- **Modular Design**: Easily integrates into ESP-IDF projects as a component.
- **Connection Status**: Check if TX notifications are enabled with `ble_bidi_fast_tx_is_notification_enabled()`.

## Requirements

- ESP-IDF v4.4 or later
- ESP32 device with BLE support
- NVS flash initialized by the user application

## Installation

1. Copy the `ble_bidi_fast` component into your ESP-IDF project's `components` directory.
2. Ensure the component is included in your project's `CMakeLists.txt` or automatically detected by ESP-IDF.
3. Initialize NVS flash in your application before using the component.

## Usage

### Example 1: Basic Usage

Below is a basic example demonstrating how to initialize the `ble_bidi_fast` component and handle data received on the RX Characteristic.

```c
#include "ble_bidi_fast.h"
#include "esp_log.h"
#include "nvs_flash.h"

static const char *TAG = "APP";

// Callback for RX received data
static void on_rx_receive_callback(const uint8_t *data, uint8_t len) {
    ESP_LOGI(TAG, "Received %d bytes on RX Characteristic", len);
    for (int i = 0; i < len; i++) {
        ESP_LOGI(TAG, "data[%d]=0x%02x", i, data[i]);
    }
}

void app_main(void) {
    // Initialize NVS flash
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    // Define 128-bit UUIDs (Little Endian)
    // Service UUID      : 6e400001-b5a3-93f3-e0a9-e50e24dcca9e
    // TX Characteristic : 6e400002-b5a3-93f3-e0a9-e50e24dcca9e
    // RX Characteristic : 6e400003-b5a3-93f3-e0a9-e50e24dcca9e
    uint8_t service_uuid[16] = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0xf3, 0x93, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e};
    uint8_t tx_uuid[16]      = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0xf3, 0x93, 0xa3, 0xb5, 0x02, 0x00, 0x40, 0x6e};
    uint8_t rx_uuid[16]      = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0xf3, 0x93, 0xa3, 0xb5, 0x03, 0x00, 0x40, 0x6e};

    // Configure BLE component
    ble_bidi_fast_config_t config = {
        .device_name = "SwiftDevice",
        .device_name_len = 11,
        .on_rx_receive_callback = on_rx_receive_callback
    };

    // Initialize BLE
    ESP_ERROR_CHECK(ble_bidi_fast_init(&config, service_uuid, tx_uuid, rx_uuid));

    // Send example data via TX Characteristic when ready
    uint8_t data[2] = {0x01, 0x02};
    if (ble_bidi_fast_tx_is_notification_enabled()) {
        ESP_ERROR_CHECK(ble_bidi_fast_tx_send(data, 2));
    }
}
```

### Example 2: Simple Echo

The `ble_simple_echo` example demonstrates bidirectional communication using the `ble_bidi_fast` component. In this example:

- When the **TX Characteristic**'s Notification is enabled (by writing `0x01 0x00` to the Client Characteristic Configuration Descriptor, CCCD), an LED starts blinking every 500ms to indicate the active notification state.
- When data is written to the **RX Characteristic**, the ESP32 immediately echoes the same data back to the client via the **TX Characteristic**.

This example is ideal for testing the component's basic functionality with a BLE client app (e.g., nRF Connect) and visualizing the notification state via an LED.

**Code**:

```c
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include <driver/gpio.h>
#include "ble_bidi_fast.h"

#define TAG "BLE_SIMPLE_ECHO"

//  2: Built-in LED on most ESP32 boards
// 15: Xiao ESP32C6
// 21: Xiao ESP32S3
#define LED_GPIO 15

// LED state
static bool s_led_on = false;

// Configure LED
static void configure_led(void) {
    gpio_config_t io_conf = {
        .pin_bit_mask = (1ULL << LED_GPIO),
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = 0,
        .pull_down_en = 0,
        .intr_type = GPIO_INTR_DISABLE
    };
    gpio_config(&io_conf);
}

// Toggle LED
static void toggle_led(void) {
    s_led_on = !s_led_on;
    gpio_set_level(LED_GPIO, s_led_on);
}

// Task to blink LED when TX Characteristic's Notification is On (CCCD: On=0x01 0x00, Off=0x00 0x00)
static void led_blink_task(void *pvParameters) {
    while (1) {
        if (ble_bidi_fast_tx_is_notification_enabled()) {
            toggle_led();
        } else {
            gpio_set_level(LED_GPIO, 0); // Stop blinking when TX Notification is Off
        }
        vTaskDelay(pdMS_TO_TICKS(500)); // 500ms
    }
}

// Callback for RX received data
static void on_rx_receive_callback(const uint8_t *data, uint8_t len) {
    ESP_LOGI(TAG, "Received %d bytes on RX Characteristic", len);
    
    // Echo back the received data via TX Characteristic
    if (ble_bidi_fast_tx_is_notification_enabled()) {
        esp_err_t ret = ble_bidi_fast_tx_send(data, len);
        if (ret) {
            ESP_LOGW(TAG, "Failed to send via TX Characteristic, error=%d", ret);
        } else {
            ESP_LOGI(TAG, "Echoed %d bytes via TX Characteristic", len);
        }
    }
}

void app_main(void) {
    ESP_LOGI(TAG, "Starting BLE Simple Echo");

    // Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_LOGW(TAG, "Erasing NVS partition");
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    ESP_LOGI(TAG, "NVS initialized");

    // Define UUIDs (Little Endian)
    // Service UUID      : 6e400001-b5a3-93f3-e0a9-e50e24dcca9e
    // TX Characteristic : 6e400002-b5a3-93f3-e0a9-e50e24dcca9e
    // RX Characteristic : 6e400003-b5a3-93f3-e0a9-e50e24dcca9e
    uint8_t service_uuid[16] = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0xf3, 0x93, 0xa3, 0xb5, 0x01, 0x00, 0x40, 0x6e};
    uint8_t tx_uuid[16]      = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0xf3, 0x93, 0xa3, 0xb5, 0x02, 0x00, 0x40, 0x6e};
    uint8_t rx_uuid[16]      = {0x9e, 0xca, 0xdc, 0x24, 0x0e, 0xe5, 0xa9, 0xe0, 0xf3, 0x93, 0xa3, 0xb5, 0x03, 0x00, 0x40, 0x6e};

    // Configure BLE
    ble_bidi_fast_config_t config = {
        .device_name = "SimpleEcho",
        .device_name_len = 10,
        .rx_receive_callback = on_rx_receive_callback,
    };

    // Initialize BLE
    ESP_ERROR_CHECK(ble_bidi_fast_init(&config, service_uuid, tx_uuid, rx_uuid));
    ESP_LOGI(TAG, "BLE initialized");

    // Configure LED
    configure_led();
    ESP_LOGI(TAG, "LED configured");

    // Start LED blink task
    xTaskCreate(led_blink_task, "led_blink_task", 2048, NULL, 5, NULL);
    ESP_LOGI(TAG, "LED blink task started");
}
```

**Testing**:

1. Flash the example to an ESP32 device (e.g., Xiao ESP32C6 with LED on GPIO 15).
2. Use a BLE client app like nRF Connect to connect to the device named `SimpleEcho`.
3. Enable notifications on the TX Characteristic (`6e400002-b5a3-93f3-e0a9-e50e24dcca9e`) by writing `0x01 0x00` to its CCCD.
4. Observe the LED blinking every 500ms.
5. Write data to the RX Characteristic (`6e400003-b5a3-93f3-e0a9-e50e24dcca9e`).
6. Verify that the same data is echoed back via the TX Characteristic.

### API

- **`ble_bidi_fast_init`**: Initializes the BLE module with the provided configuration and UUIDs. Returns `ESP_OK` on success or an error code on failure.
- **`ble_bidi_fast_tx_send`**: Transmits data to the connected client using the Notify property of the TX Characteristic. Returns `ESP_OK` on success or `ESP_ERR_INVALID_STATE` if notifications are not enabled or data length is invalid.
- **`ble_bidi_fast_tx_is_notification_enabled`**: Checks if the client has enabled notifications on the TX Characteristic. Returns `true` if notifications are enabled, `false` otherwise.
- **`rx_receive_callback`**: User-defined callback invoked when data is received from the client via the RX Characteristic.

## Notes

- **Device Name Length**: Keep the device name under 20 bytes to fit within the 31-byte advertising data limit.
- **NVS Initialization**: The user application must initialize NVS flash before calling `ble_bidi_fast_init`.
- **UUIDs**: Use 128-bit UUIDs for the service and characteristics to ensure uniqueness.
- **Error Handling**: Check return values of API functions to handle errors appropriately.
- **Connection Parameters**: The component sets preferred connection parameters (7.5ms–15ms interval, 0s latency, 4s timeout) for low-latency communication.

## License

MIT License. See `LICENSE` file for details.

Links

Supports all targets

License: MIT

To add this component to your project, run:

idf.py add-dependency "shoderico/ble_bidi_fast^1.0.3"

or download archive

Stats

  • Archive size
    Archive size ~ 13.57 KB
  • Downloaded in total
    Downloaded in total 4 times
  • Downloaded this version
    This version: 1 time

Badge

shoderico/ble_bidi_fast version: 1.0.3
|