Page 1 of 2

Blutooth example.

Posted: Thu Feb 18, 2021 2:18 am
by User4356
Hello.

I need to connect two ESP32 devices via blutooth and I am looking for a working example of this task. One device will send data, the other will receive and do something. I know there have been many projects like this, but I'm a beginner and haven't found a single example. Can you help me with this, pls?

My best regards,
User4356.

Re: Blutooth example.

Posted: Thu Feb 18, 2021 9:41 am
by ESP_Minatel
Hi,

You can try the GATT Client and Server examples on our GitHub.

GATT Client
GATT Server

Hope this could help you!

Re: Blutooth example.

Posted: Fri Feb 19, 2021 2:19 pm
by User4356
Thank you for answer.
Now I'm studying the bluetooth specification and found out that there are two versions: Bluetooth Classic and Bluetooth Low Energy. I have no experience at all, but the task that I want to implement is to transmit audio over a wireless. Do I understand correctly that I need a classic bluetooth? Which of these specifications is implemented in your example?

Re: Blutooth example.

Posted: Fri Feb 19, 2021 2:29 pm
by User4356
I just noticed that this is not just an example, this is a whole tutorial! This can be very, very helpful. Thank you very much again. But in the description, the example uses the Blutooth Low Energy version, and I need sound transmission. Tell me, is there a similar tutorial for classic bluetooth? Or maybe there is an opportunity in a simple way to convert it to the Bluetooth Classic standart? Or maybe I can implement my task on Blutooth Low Energy?

Re: Blutooth example.

Posted: Mon Feb 22, 2021 12:54 pm
by ESP_Minatel
Hi,

I suggest you to use BLE instead of Classic.

We also provide you a development framework for audio: ESP-ADF

Re: Blutooth example.

Posted: Fri Feb 26, 2021 12:59 am
by User4356
Thank you for response!

Now I am reading documentation and I found an inaccuracy.
In: https://github.com/espressif/esp-idf/bl ... cteristics

In paragraph:
"First, the service handle generated by the BLE stack is stored in the profile table, which will be used later by the application layer to refer to this service. Then, the UUID of the characteristic and its UUID length are set. The length of the characteristic UUID is again 16 bits. The service is started using the esp_ble_gatts_start_service() function with the service handle previously generated. An ESP_GATTS_START_EVT event, which is used to print information, is triggered. The characteristic is added to the service by the esp_ble_gatts_start_service() function in conjunction with the characteristics permissions and properties. In this example, the characteristics in both profiles are set up as follows:"
Sentence:
"The characteristic is added to the service by the esp_ble_gatts_start_service() function"
seems not a true. As I understand code, characteristic added by that function:

Code: Select all

        esp_err_t add_char_ret = esp_ble_gatts_add_char(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].char_uuid,
                                                        ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
                                                        a_property,
                                                        &gatts_demo_char1_val, NULL);
Correct me, I am wrong.

Re: Blutooth example.

Posted: Fri Feb 26, 2021 10:32 am
by ESP_Minatel
Hi,

Thank you for reporting! We will check and review this information.

Re: Blutooth example.

Posted: Fri Feb 26, 2021 10:26 pm
by User4356
I finished server tutorial, but there is some code not explained. Can you tell me, what this code do?

Code: Select all

    case ESP_GATTS_WRITE_EVT: {
        ESP_LOGI(GATTS_TAG, "GATT_WRITE_EVT, conn_id %d, trans_id %d, handle %d", param->write.conn_id, param->write.trans_id, param->write.handle);
        if (!param->write.is_prep){
            ESP_LOGI(GATTS_TAG, "GATT_WRITE_EVT, value len %d, value :", param->write.len);
            esp_log_buffer_hex(GATTS_TAG, param->write.value, param->write.len);
            if (gl_profile_tab[PROFILE_A_APP_ID].descr_handle == param->write.handle && param->write.len == 2){
                uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0];
                if (descr_value == 0x0001){
                    if (a_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY){
                        ESP_LOGI(GATTS_TAG, "notify enable");
                        uint8_t notify_data[15];
                        for (int i = 0; i < sizeof(notify_data); ++i)
                        {
                            notify_data[i] = i%0xff;
                        }
                        //the size of notify_data[] need less than MTU size
                        esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_A_APP_ID].char_handle,
                                                sizeof(notify_data), notify_data, false);
                    }
                }else if (descr_value == 0x0002){
                    if (a_property & ESP_GATT_CHAR_PROP_BIT_INDICATE){
                        ESP_LOGI(GATTS_TAG, "indicate enable");
                        uint8_t indicate_data[15];
                        for (int i = 0; i < sizeof(indicate_data); ++i)
                        {
                            indicate_data[i] = i%0xff;
                        }
                        //the size of indicate_data[] need less than MTU size
                        esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_A_APP_ID].char_handle,
                                                sizeof(indicate_data), indicate_data, true);
                    }
                }
                else if (descr_value == 0x0000){
                    ESP_LOGI(GATTS_TAG, "notify/indicate disable ");
                }else{
                    ESP_LOGE(GATTS_TAG, "unknown descr value");
                    esp_log_buffer_hex(GATTS_TAG, param->write.value, param->write.len);
                }
            }
        }
        example_write_event_env(gatts_if, &a_prepare_write_env, param);
        break;
    }

Re: Blutooth example.

Posted: Sun Feb 28, 2021 11:50 pm
by User4356
There is something else I dont undestand.
Here: https://github.com/espressif/esp-idf/bl ... g-services
The register event is also used to create a profile attributes table by using the esp_ble_gatts_create_attr_tab() function, which takes an esp_gatts_attr_db_t type structure that has all the information of the service table. The way to create this table is:

Code: Select all

…
esp_ble_gatts_create_service(gatts_if, &gl_profile_tab[PROFILE_A_APP_ID].service_id, GATTS_NUM_HANDLE_TEST_A);
break;
…
First it is talking about esp_ble_gatts_create_attr_tab() function, but there is no that function in example code. In example code is esp_ble_gatts_create_service() function. So, how to use esp_ble_gatts_create_attr_tab and when?

Why there is no esp_ble_gatts_create_attr_tab() function in example of gatt server?
https://github.com/espressif/esp-idf/bl ... tts_demo.c

Re: Blutooth example.

Posted: Mon Mar 01, 2021 11:44 pm
by User4356
Another one misunderstanding in tutorials.
https://github.com/espressif/esp-idf/bl ... through.md
The initialization of the Application Profile table array includes defining the callback functions for each Profile. These are gattc_profile_a_event_handler() and gattc_profile_a_event_handler() respectively. In addition, the GATT interface is initialized to the default value of ESP_GATT_IF_NONE. Later on, when the Application Profile is registered, the BLE stack returns a GATT interface instance to use with that Application Profile.
Just read the second sentence. Besides the fact that the same function is repeated twice, it is also not correct. Correct function is: gattc_profile_event_handler().

(I hope somebody read that topic)