nkolban / esp32-snippets

Sample ESP32 snippets and code fragments
https://leanpub.com/kolban-ESP32
Apache License 2.0
2.33k stars 709 forks source link

Support multiple instances of the same service type #532

Open jim-ber opened 6 years ago

jim-ber commented 6 years ago

Currently, the BLEServer::createService will not allow the creation of services with the same UUID as a previously added service. It would be useful to add multiple instances of the same service. For example, a medical device could aggregate readings from multiple heart rate sensors throughout the body and display them in a single BLE Device (with different Body Sensor Location characteristics).

chegewara commented 6 years ago

It is not allowed by bluetooth specs to have more than one service with the same UUID, correct me if im wrong, but you can have multiple characteristics with the same UUID (this is implemented in this library) and it will work with your example. Body sensor location is described in descriptor so each characteristic can have own dscriptor that will tell where sensor is attached.

jim-ber commented 6 years ago

I am going to check spec and get back to you! But I have not seen anywhere that specifies that creating multiple services with the same UUID isn't permitted. Considering that services can be uniquely identified on the GATT Server side by handle, I don't really see a technical impediment either.

Here is what I have found: 1 2 3

Let me do some research into the spec and I'll post my findings.

jim-ber commented 6 years ago

What I have found so far here under 4.4.2: Discover Primary Service by Service UUID says that a specific primary service may exist multiple times on a server.

chegewara commented 6 years ago

I thought ive read somewhere its not possible, but your finding is very good. Thanks.

I will investigate if its possible to add this with current esp-idf and will try to add this, just need some time.

chegewara commented 6 years ago

From my early tests i can say that esp-idf is not allowing it:

I (716) BT_GATT: GATTS_StartService
I (725) BT_GATT: GATTS_StartService
E (726) BT_GATT: Active Service Found
E (729) BT_GATT: Duplicate Service start - Service already started
I (738) BT_APPL: BTA_DmSetBleAdvParamsAll: 32, 64
jim-ber commented 6 years ago

Thank you for all your help! @chegewara

I just found this in the executeCreate method in BLEService.

srvc_id.id.inst_id = 0;

I haven't tried it yet but maybe incrementing that instance id when adding a service with the same uuid may fix the issue?

I just checked the esp-idf here and this snippet seems to indicate that it might:

/*******************************************************************************
**
** Function         GATTS_CreateService
**
** Description      This function is called to reserve a block of handles for a service.
**
**                  *** It should be called only once per service instance  ***
**
** Parameter        gatt_if       : application if
**                  p_svc_uuid    : service UUID
**                  svc_inst      : instance of the service inside the application
**                  num_handles   : number of handles needed by the service.
**                  is_pri        : is a primary service or not.
**
** Returns          service handle if sucessful, otherwise 0.
**
*******************************************************************************/
UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
                            UINT16 svc_inst, UINT16 num_handles, BOOLEAN is_pri)

I also think it explains your comment in espressif/esp-idf#2005 . since GATTS_CreateService returns the s_handle for the existing service if it finds a match. I am guessing it has to match all three parameters in line 64, including svc_instance.

chegewara commented 6 years ago

Good finding, seems that new handle value is created with changed srvc_id.id.inst_id. I have early version of this, could you test it and give some feedback? I will push it to my repo before i create PR. https://github.com/chegewara/esp32-snippets

jim-ber commented 6 years ago

I can tonight. I'll post back with some feedback. Thanks!

chegewara commented 6 years ago

Just for testing purpose it works only with two services with the same uuid.

chegewara commented 6 years ago

For multiple services with the same uuid additional parameter has been added. It requires that programmer keep properly create service with this parameter:

 BLEService* pService2 = pServer->createService(BLEUUID("03b80e5a-ede8-4b33-a751-6ce34ec4c700"), 15, 2);
BLEService* pService3 = pServer->createService(BLEUUID("03b80e5a-ede8-4b33-a751-6ce34ec4c700"), 15, 3);

Last parameter is type of uint8_t and can have value from 0 to 255.

jim-ber commented 6 years ago

@chegewara Sorry about the delay. Tested it and it works (tested it up to 16 services).

Thanks!

chegewara commented 6 years ago

@jim-ber I just found issue that needs to be addressed with latest PR. This part of code does not test against srvc_id.id.inst_id: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEServer.cpp#L220-L221

jim-ber commented 6 years ago

@chegewara I'll fix it tonight. Thanks for pointing that out!

frazan-un commented 5 years ago

Hi all, I'm trying to do the same thing (2 services with the same UUID) using the attribute tables. The function that crate that (esp_ble_gatts_create_attr_tab()) is ok because there is an argument srvc_inst_id, and so I can call it 2 times with different service instances. My problem is that in the event generated (ESP_GATTS_CREAT_ATTR_TAB_EVT) I can't find a reference to the service instance in order to save the handles in different places: gatts_add_attr_tab_evt_param contains only a esp_bt_uuid_t not a esp_gatt_srvc_id_t like the gatts_create_evt_param where instance ID can be found. Is there a way to resolve this or can't be done using attr tables? Thanks!

chegewara commented 5 years ago

Hi @frazan-un if i remember multiple services with the same uuid is not finished in this library yet.

About srvc_inst_id in ESP_GATTS_CREAT_ATTR_TAB_EVT you can ask espressif devs on esp-idf github issues tracker. I believe they will add it or explain how to write code without it if its not needed.