From 73c9541920e39ffb752e6514bae25ffb68188f4e Mon Sep 17 00:00:00 2001 From: Chen Jian Hua Date: Tue, 1 Apr 2025 09:30:45 +0800 Subject: [PATCH] feat(bt/bluedroid): Added BLE eddystone sender example (cherry picked from commit 06366353d862e38eae1aa4cbf9f1781eed62767e) Co-authored-by: zhangbowen --- .../CMakeLists.txt | 0 .../README.md | 0 .../main/CMakeLists.txt | 0 .../main/esp_eddystone_api.c | 0 .../main/esp_eddystone_api.h | 0 .../main/esp_eddystone_demo.c | 0 .../main/esp_eddystone_protocol.h | 2 +- .../sdkconfig.defaults | 0 .../sdkconfig.defaults.esp32c2 | 0 .../sdkconfig.defaults.esp32c3 | 0 .../sdkconfig.defaults.esp32s3 | 0 .../ble/ble_eddystone_sender/CMakeLists.txt | 6 + .../ble/ble_eddystone_sender/README.md | 50 +++++ .../ble_eddystone_sender/main/CMakeLists.txt | 2 + .../main/Kconfig.projbuild | 22 ++ .../main/esp_eddystone_api.h | 59 +++++ .../main/esp_eddystone_demo.c | 209 ++++++++++++++++++ .../main/esp_eddystone_protocol.h | 156 +++++++++++++ .../ble_eddystone_sender/sdkconfig.defaults | 11 + .../sdkconfig.defaults.esp32c2 | 10 + .../sdkconfig.defaults.esp32c3 | 7 + .../sdkconfig.defaults.esp32s3 | 7 + 22 files changed, 540 insertions(+), 1 deletion(-) rename examples/bluetooth/bluedroid/ble/{ble_eddystone => ble_eddystone_receiver}/CMakeLists.txt (100%) rename examples/bluetooth/bluedroid/ble/{ble_eddystone => ble_eddystone_receiver}/README.md (100%) rename examples/bluetooth/bluedroid/ble/{ble_eddystone => ble_eddystone_receiver}/main/CMakeLists.txt (100%) rename examples/bluetooth/bluedroid/ble/{ble_eddystone => ble_eddystone_receiver}/main/esp_eddystone_api.c (100%) rename examples/bluetooth/bluedroid/ble/{ble_eddystone => ble_eddystone_receiver}/main/esp_eddystone_api.h (100%) rename examples/bluetooth/bluedroid/ble/{ble_eddystone => ble_eddystone_receiver}/main/esp_eddystone_demo.c (100%) rename examples/bluetooth/bluedroid/ble/{ble_eddystone => ble_eddystone_receiver}/main/esp_eddystone_protocol.h (98%) rename examples/bluetooth/bluedroid/ble/{ble_eddystone => ble_eddystone_receiver}/sdkconfig.defaults (100%) rename examples/bluetooth/bluedroid/ble/{ble_eddystone => ble_eddystone_receiver}/sdkconfig.defaults.esp32c2 (100%) rename examples/bluetooth/bluedroid/ble/{ble_eddystone => ble_eddystone_receiver}/sdkconfig.defaults.esp32c3 (100%) rename examples/bluetooth/bluedroid/ble/{ble_eddystone => ble_eddystone_receiver}/sdkconfig.defaults.esp32s3 (100%) create mode 100644 examples/bluetooth/bluedroid/ble/ble_eddystone_sender/CMakeLists.txt create mode 100644 examples/bluetooth/bluedroid/ble/ble_eddystone_sender/README.md create mode 100644 examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/CMakeLists.txt create mode 100644 examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/Kconfig.projbuild create mode 100644 examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/esp_eddystone_api.h create mode 100644 examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/esp_eddystone_demo.c create mode 100644 examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/esp_eddystone_protocol.h create mode 100644 examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults create mode 100644 examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32c2 create mode 100644 examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32c3 create mode 100644 examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32s3 diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone/CMakeLists.txt b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/CMakeLists.txt similarity index 100% rename from examples/bluetooth/bluedroid/ble/ble_eddystone/CMakeLists.txt rename to examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/CMakeLists.txt diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone/README.md b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/README.md similarity index 100% rename from examples/bluetooth/bluedroid/ble/ble_eddystone/README.md rename to examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/README.md diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone/main/CMakeLists.txt b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/CMakeLists.txt similarity index 100% rename from examples/bluetooth/bluedroid/ble/ble_eddystone/main/CMakeLists.txt rename to examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/CMakeLists.txt diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone/main/esp_eddystone_api.c b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_api.c similarity index 100% rename from examples/bluetooth/bluedroid/ble/ble_eddystone/main/esp_eddystone_api.c rename to examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_api.c diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone/main/esp_eddystone_api.h b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_api.h similarity index 100% rename from examples/bluetooth/bluedroid/ble/ble_eddystone/main/esp_eddystone_api.h rename to examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_api.h diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone/main/esp_eddystone_demo.c b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_demo.c similarity index 100% rename from examples/bluetooth/bluedroid/ble/ble_eddystone/main/esp_eddystone_demo.c rename to examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_demo.c diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone/main/esp_eddystone_protocol.h b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_protocol.h similarity index 98% rename from examples/bluetooth/bluedroid/ble/ble_eddystone/main/esp_eddystone_protocol.h rename to examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_protocol.h index 028871708b..ee29e83359 100644 --- a/examples/bluetooth/bluedroid/ble/ble_eddystone/main/esp_eddystone_protocol.h +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_receiver/main/esp_eddystone_protocol.h @@ -59,7 +59,7 @@ typedef struct { uint16_t batt; /* +``` + +Switch sending mode UID or URL or TLM: +Go to: `idf.py menuconfig --> Component config --> Example 'EDDYSTONE SEND' -->` then select the `EXMAPLE_EDDYSTONE_SEND` option. + +### Hardware Required + +* A development board with ESP32/ESP32-C3/ESP32-H2/ESP32-C2/ESP32-S3 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) +* A USB cable for Power supply and programming + +See [Development Boards](https://www.espressif.com/en/products/devkits) for more information about it. + +### Build and Flash + +Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://idf.espressif.com/) for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +``` +I (532) EDDYSTONE_DEMO: Register callback +I (532) EDDYSTONE_DEMO: Raw advertising data set complete +I (532) EDDYSTONE_DEMO: Advertising started successfully +I (542) main_task: Returned from app_main() +``` + +## Troubleshooting + +For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon. diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/CMakeLists.txt b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/CMakeLists.txt new file mode 100644 index 0000000000..a9b9b14bd0 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "esp_eddystone_demo.c" + INCLUDE_DIRS "") diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/Kconfig.projbuild b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/Kconfig.projbuild new file mode 100644 index 0000000000..39ac4331da --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/Kconfig.projbuild @@ -0,0 +1,22 @@ +menu "Example 'EDDYSTONE SENDER' Config" + + choice EXMAPLE_EDDYSTONE_SEND + prompt "Eddystone frame type" + default EXMAPLE_EDDYSTONE_SEND_UID + help + The type of Eddystone frame to be sent + config EXMAPLE_EDDYSTONE_SEND_UID + bool "Frame type UID" + config EXMAPLE_EDDYSTONE_SEND_URL + bool "Frame type URL" + config EXMAPLE_EDDYSTONE_SEND_TLM + bool "Frame type TLM" + endchoice + + config EXMAPLE_EDDYSTONE_SEND + int + default 0 if EXMAPLE_EDDYSTONE_SEND_UID + default 1 if EXMAPLE_EDDYSTONE_SEND_URL + default 2 if EXMAPLE_EDDYSTONE_SEND_TLM + +endmenu diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/esp_eddystone_api.h b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/esp_eddystone_api.h new file mode 100644 index 0000000000..b8f55c9b03 --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/main/esp_eddystone_api.h @@ -0,0 +1,59 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + + +#ifndef __ESP_EDDYSTONE_API_H__ +#define __ESP_EDDYSTONE_API_H__ + +typedef struct { + struct { + uint8_t flags; /*! the encoded URL */ + char url[EDDYSTONE_URL_MAX_LEN]; /* +#include +#include +#include + +#include "esp_bt.h" +#include "nvs_flash.h" +#include "esp_log.h" +#include "esp_bt_defs.h" +#include "esp_bt_main.h" +#include "esp_gatt_defs.h" +#include "esp_gattc_api.h" +#include "esp_gap_ble_api.h" +#include "freertos/FreeRTOS.h" + +#include "esp_eddystone_protocol.h" +#include "esp_eddystone_api.h" + +static const char* DEMO_TAG = "EDDYSTONE_DEMO"; + +/* declare static functions */ +static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param); +static void eddystone_send_raw(const esp_eddystone_result_t *res); + +static esp_ble_adv_params_t adv_params = { + .adv_int_min = 0x20, + .adv_int_max = 0x40, + .adv_type = ADV_TYPE_IND, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, +}; + +static void eddystone_send_raw(const esp_eddystone_result_t *res) +{ + uint8_t raw_adv_data[31] = {0}; + uint8_t index =0; + + raw_adv_data[index++] = 2; // length + raw_adv_data[index++] = ESP_BLE_AD_TYPE_FLAG; + raw_adv_data[index++] = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT); + raw_adv_data[index++] = 3; //length + raw_adv_data[index++] = ESP_BLE_AD_TYPE_16SRV_CMPL; + raw_adv_data[index++] = 0xAA; //uuid for eddystone + raw_adv_data[index++] = 0xFE; + + switch(res->common.frame_type) + { + case EDDYSTONE_FRAME_TYPE_UID: { + raw_adv_data[index++] = 23; //length + raw_adv_data[index++] = ESP_BLE_AD_TYPE_SERVICE_DATA; + raw_adv_data[index++] = 0xAA; + raw_adv_data[index++] = 0xFE; + uint8_t service_data[EDDYSTONE_UID_DATA_LEN+3] = {0}; + service_data[0] = EDDYSTONE_FRAME_TYPE_UID; + service_data[1] = res->inform.uid.ranging_data; + memcpy(&service_data[2], res->inform.uid.namespace_id, EDDYSTONE_UID_NAMESPACE_LEN); + memcpy(&service_data[12], res->inform.uid.instance_id, EDDYSTONE_UID_INSTANCE_LEN); + service_data[18] = 0x00; + service_data[19] = 0x00; + memcpy(&raw_adv_data[index], service_data, EDDYSTONE_UID_DATA_LEN+3); + index += EDDYSTONE_UID_DATA_LEN + 3; + break; + } + + case EDDYSTONE_FRAME_TYPE_URL: { + size_t url_len = strlen((char*)res->inform.url.encoded_url); //encoded url length + if(url_len > EDDYSTONE_URL_MAX_LEN){ + url_len = EDDYSTONE_URL_MAX_LEN; + } + + raw_adv_data[index++] = url_len+6; //length + raw_adv_data[index++] = ESP_BLE_AD_TYPE_SERVICE_DATA; + raw_adv_data[index++] = 0xAA; + raw_adv_data[index++] = 0xFE; + uint8_t service_data[EDDYSTONE_URL_MAX_LEN+2] = {0}; + service_data[0] = EDDYSTONE_FRAME_TYPE_URL; + service_data[1] = res->inform.url.tx_power; + service_data[2] = res->inform.url.url_scheme; + memcpy(&service_data[3], res->inform.url.encoded_url, url_len); + memcpy(&raw_adv_data[index], service_data, url_len+3); + index += url_len+3; + break; + } + + case EDDYSTONE_FRAME_TYPE_TLM: { + raw_adv_data[index++] = 17; //length + raw_adv_data[index++] = ESP_BLE_AD_TYPE_SERVICE_DATA; + raw_adv_data[index++] = 0xAA; + raw_adv_data[index++] = 0xFE; + uint8_t service_data[EDDYSTONE_TLM_DATA_LEN+1] = {0}; + service_data[0] = EDDYSTONE_FRAME_TYPE_TLM; + service_data[1] = res->inform.tlm.version; + service_data[2] = (res->inform.tlm.battery_voltage >> 8) & 0xFF; + service_data[3] = res->inform.tlm.battery_voltage & 0xFF; + service_data[4] = (res->inform.tlm.temperature >> 8) & 0xFF; + service_data[4] = res->inform.tlm.temperature & 0xFF; + service_data[6] = (res->inform.tlm.adv_count >> 24) & 0xFF; + service_data[7] = (res->inform.tlm.adv_count >> 16) & 0xFF; + service_data[8] = (res->inform.tlm.adv_count >> 8) & 0xFF; + service_data[9] = res->inform.tlm.adv_count & 0xFF; + service_data[10] = (res->inform.tlm.time >> 24) & 0xFF; + service_data[11] = (res->inform.tlm.time >> 16) & 0xFF; + service_data[12] = (res->inform.tlm.time >> 8) & 0xFF; + service_data[13] = res->inform.tlm.time & 0xFF; + memcpy(&raw_adv_data[index], service_data, EDDYSTONE_TLM_DATA_LEN+1); + index += EDDYSTONE_TLM_DATA_LEN+1; + break; + } + + default: + break; + } + esp_ble_gap_config_adv_data_raw(raw_adv_data, index); +} + +static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) +{ + switch(event) + { + case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: { + ESP_LOGI(DEMO_TAG,"Raw advertising data set complete"); + esp_ble_gap_start_advertising(&adv_params); + break; + } + + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: { + if(param->adv_start_cmpl.status == ESP_BT_STATUS_SUCCESS){ + ESP_LOGI(DEMO_TAG,"Advertising started successfully"); + }else{ + ESP_LOGE(DEMO_TAG,"Failed to start advertising, error code = %x",param->adv_start_cmpl.status); + } + break; + } + + default: + break; + } +} + +void esp_eddystone_appRegister(void) +{ + esp_err_t status; + + ESP_LOGI(DEMO_TAG,"Register callback"); + + /*= 0x00 && ch <= 0x20) || (ch >= 0x7f && ch <= 0xff); +} + +#endif /* __ESP_EDDYSTONE_PROTOCOL_H__ */ diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults new file mode 100644 index 0000000000..93b417c68f --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults @@ -0,0 +1,11 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_BT_ENABLED=y +# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +# CONFIG_BT_LE_50_FEATURE_SUPPORT is not used on ESP32, ESP32-C3 and ESP32-S3. +# CONFIG_BT_LE_50_FEATURE_SUPPORT is not set +CONFIG_EXMAPLE_EDDYSTONE_SEND_UID=y +CONFIG_EXMAPLE_EDDYSTONE_SEND_URL=n +CONFIG_EXMAPLE_EDDYSTONE_SEND_TLM=n diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32c2 b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32c2 new file mode 100644 index 0000000000..0b64f8ea4a --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32c2 @@ -0,0 +1,10 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32c2" +CONFIG_BT_ENABLED=y +# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +# CONFIG_BT_LE_50_FEATURE_SUPPORT is not set +CONFIG_BT_LE_HCI_EVT_BUF_SIZE=257 +CONFIG_XTAL_FREQ_26=y diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32c3 b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32c3 new file mode 100644 index 0000000000..0ad7bbc0ae --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32c3 @@ -0,0 +1,7 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32c3" +CONFIG_BT_ENABLED=y +# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y diff --git a/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32s3 b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32s3 new file mode 100644 index 0000000000..2a50f1657b --- /dev/null +++ b/examples/bluetooth/bluedroid/ble/ble_eddystone_sender/sdkconfig.defaults.esp32s3 @@ -0,0 +1,7 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32s3" +CONFIG_BT_ENABLED=y +# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y