# 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.
idf.py add-dependency "shoderico/ble_bidi_fast^1.0.3"