espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.51k stars 7.26k forks source link

[TW#12193] GATT_Server and GATT_Client not running together at the same time. #404

Closed lucashutchinson closed 7 years ago

lucashutchinson commented 7 years ago

Hi All,

I am trying to set-up and ESP32 with both a GATT Server and a GATT Clent running at the same time.

I have based this directly off the gatt_server_service_table and the gatt_server examples from the esp-idf, with the only real modifications done to the initialization as explained below.

I have tried doing this:

        esp_bt_controller_init();
    if (esp_bt_controller_enable(ESP_BT_MODE_BTDM))
    {
        ESP_LOGE(SYRP_GATT_TAG, "Fatal Error! %s enable controller failed\n", __func__);
        return;
    }

    if (esp_bluedroid_init())
    {
        ESP_LOGE(SYRP_GATT_TAG, "Fatal Error! %s init bluetooth failed\n", __func__);
        return;
    }

    if (esp_bluedroid_enable())
    {
        ESP_LOGE(SYRP_GATT_TAG, "Fatal Error! %s enable bluetooth failed\n", __func__);
        return;
    }
    ESP_LOGI(SYRP_GATT_TAG, "%s Bluetooth Setup Complete\n", __func__);

    gatt_client_main();
    gatt_server_main();

Where gatt_client_main() performs the following: (this replaces the app_main in the gatt_client example)

    esp_err_t status;
    //register the scan callback function to the gap moudule
    if ((status = esp_ble_gap_register_callback(esp_gap_cb)) != ESP_OK) {
        ESP_LOGE(GATTC_TAG, "gap register error, error code = %x\n", status);
        return;
    }

    //register the callback function to the gattc module
    if ((status = esp_ble_gattc_register_callback(esp_gattc_cb)) != ESP_OK) {
        ESP_LOGE(GATTC_TAG, "gattc register error, error code = %x\n", status);
        return;
    }
    esp_ble_gattc_app_register(PROFILE_A_APP_ID);
    esp_ble_gattc_app_register(PROFILE_B_APP_ID);

And gatt_server_main performs the following: (this replaces the app_main in the gatt_server example)

 esp_ble_gatts_register_callback(gatts_event_handler);
    esp_ble_gap_register_callback(gap_event_handler);
    esp_ble_gatts_app_register(ESP_HEART_RATE_APP_ID);

However whenever this program runs, the GATT_Client will startup and run correctly, but the GATT_Server does not seem start correctly, and does not advertise.

Similarly, when I reverse the initialization order, eg call `gatt_server_main' then 'gatt_client_main' the reverse happens. The gatt server will start correctly and advertise, while the gatt client doesnt seem to initialize properly and will not start scanning.

Is this the expected outcome of this setup? Is the ESP32 able to support both a GATT Client and a GATT Server at the same time? Is this support currently in the IDF?

Is there anything that i am missing or not doing correctly here?

Thanks in advance!

heyinling commented 7 years ago

HI,

Do you mean the error is "can't advertising when scanning or can't scanning when advertising"?

If yes, then ESP32 do not support advertising and scanning at the same time. While not reporting error code when you start scan/adv when it's advertising/scanning is a bug.

If no, please let me know the error you meet.

Thanks!

HardwireIO commented 7 years ago

Hi @heyinling

"ESP32 do not support advertising and scanning at the same time" means this feature is not supported on the current IDF or there's an hardware limitation?

We are also interested to advertise during scan...

Federico

lucashutchinson commented 7 years ago

Hi @heyinling

When i call gatt_client_main then gatt_server_main I get the error Advertising start failed When i call gatt_server_main then gatt_client_main I get the error Scan start failed

I would be very good if the esp32 could support this feature in the future as i am very interested in this just like @HardwireIO

heyinling commented 7 years ago

Hi @lucashutchinson @HardwireIO ,

For what I know now, It's a limitation of controller. Need further confirmation by @TianHao-Espressif .

TianHao-Yoursmake commented 7 years ago

Hi, the GATT-SERVER and GATT-CLIENT could coexist simultaneously. But if the device is in advertising, it should stop advertising before it connect to other device. Controller do the limit(such as advertise and scan cannot send simultaneously). You can use them time-division. We will do more work about that.

nathan07 commented 7 years ago

Hi @TianHao-Espressif and @lucashutchinson , is there any news about running gatt-client and gatt-server simultaneously ? I would like to run client before server, can you provide me a way to do that ? Thanks in advance

lucashutchinson commented 7 years ago

Hi @nathan07

I have only just started getting back into Client + Server running at the same time this week. However I do thing i have made some progress.

As @TianHao-Espressif stated above the client and servers seem to be ablr run simultaneously. The only limitation is that you can't advertise and scan for devices at the same time (IMO a reasonable limitation).

I have done a simple app based off the GATT_Client and GATT_Server examples int he esp-idf. essentially i start the client application, scan for devices. Then if a match the a pre-defined device is found, then I stop scanning. Initate a connection and then start the server application, which triggers the esp32 to start advertising. I can then connect to the esp32 using my phone and the esp32 doesn't seem to disconnect from the peripheral connected to the gatt_client app.

This all seems to work. however not much testing has gone into this to see how stable this is.

I am going to be doing some more testing over the next few days, likely just performing data passthrough between two peripheral esp32's connected to an esp32 that is acting as both a central and peripherl. Where the data from the two connected devices will be funneled though an esp32 acting as a hub, which will then forward the data to a phone.

nathan07 commented 7 years ago

Thank you for your quick response @lucashutchinson ! The use case you described is exactly the same as mine ! Tell me if i'm wrong, but stop scanning is done automatically when the pre-defined device is found, raising the ESP_GAP_BLE_SCAN_RESULT_EVT event ?

lucashutchinson commented 7 years ago

Hi @nathan07 Sorry for the delay, In the example app I believe it is done like this, yes.

You can manually stop it at any time, or you can just wait for the scan to timeout. (i believe it is set to a 30s scan time in the example)

nathan07 commented 7 years ago

Ok thank you @lucashutchinson . I can connect my server module to my client/server module and then my smartphone to my client/server module. But how do you manage the transfert of data ? @TianHao-Espressif talked about time-division, but some events arrive at any moment.

nathan07 commented 7 years ago

Hi @lucashutchinson , have you made some progress in your work ? Connection between a central module and a peripheral module works fine, but I can't connect other peripherals. It seems that the central module can't launch a new scan after connecting with the smartphone. Did you find a solution ?

markterrill commented 7 years ago

I'm very interested in this 'gateway' use case, where one esp32 is managing multiple peripherals simultaneously, and working with a smartphone app

lixianyu commented 7 years ago

@lucashutchinson , when use "time-division", it is work fine!^_^

bencoman commented 7 years ago

Hi @lucashutchinson @HardwireIO ,

My use case is detecting the proximity of devices based on their GPS position. Each device should connectionlessly advertise its GPS over bluetooth, so I'm not interested in GATT, only GAP. I have this working with advertising and scanning in separate devices, but I need each device to simultaneously advertise and scan. I didn't see any code samples at #741. IIUC, I need to suspend scanning to send an advertisement. Could you advise what sequence of functions to call to do this?

Actually, just to check I'm not on the wrong track, my issue is setting up the callback with (I beleieve) all the advertising code commented out, I get... ERROR: gap register error, error code = 103 from... esp_bluedroid_init(); esp_bluedroid_enable(); if ((status = esp_ble_gap_register_callback(esp_gap_listener_cb)) != ESP_OK) { Serial.printf("ERROR: gap register error, error code = %x\n", status); return;

lucashutch commented 7 years ago

Hi @bencoman

I use just the general esp_ble_gap functions to start and stop scanning.

The general steps: Start advertising:

Stop Advertising:

Start scanning:

stop scanning:

I do not believe you would need to set the scan params, or advertising param each time you start scanning or advertising. I believe you would only set these if you wish to update them.

Other than that I call the above functions to stop advertising then start scanning and vise versa.

Hopefully this helps~

bencoman commented 7 years ago

@lucazader Thanks for your tips. The hackathon is over, but I will be continuing the project.