espressif / esp-nimble

A fork of NimBLE stack, for use with ESP32 and ESP-IDF
Apache License 2.0
78 stars 51 forks source link

Service changes in run time are not getting refreshed in ios BLE clients even upon implementing the refresh characteristics in server #72

Open BestBot7 opened 1 month ago

BestBot7 commented 1 month ago

I have implemented the refresh characteristics with service UUID 0x1801 and characteristic UUID 0x2a05 which are meant for indicating the service changes in the server to the ios BLE clients. I have implemented this on esp32c3. In nrf connect mobile app for android, we have a feature to refresh services in the run time with keeping the connection. But ios requires an indication to refresh the services and detect service change. I am not receiving any indication in my mobile app. Please help me in implementing this refresh characteristics properly and how to check the indication value on my ios mobile. Thanks in advance.

rahult-github commented 1 month ago

Hi @BestBot7 ,

The service change characteristic should be exposed from server side. Only then client will subscribe to it and when notification is sent on that characteristic the client should do operations.

From gatt server side, ensure ble_svc_gatt_init () is invoked and confirm the characteristic is seen when a client does service discovery.

BLE_GAP_EVENT_SUBSCRIBE should be then handled on server side to know that client has subscribed. If you are showing the service / characteristic , but client doesn't subscribe, then you need to check client side implementation .

Also, for your use case ble_svc_gatt_changed API can be invoked with relevant parameters to let remote know that a service is modifed which ideally should cause client to redo discovery.

Please note, that it is observed that some iOS version caches the service information in order to avoid re-discovery. So you should keep this in mind while testing against iOS.

BestBot7 commented 1 month ago

Hi @rahult-github, thanks for the response! The service and characteristics for service changed is visible in BLE client app, but upon service change, the re-discovery is not happening. I am using nrf connect mobile installed in iphone 13 starlight 128 GB specs. I have also tried in android mobile nrf connect app but the indication value is not acquired by the mobile app even after subscribing to the service (or not sent by the server? no idea). I wanted to know what am I missing to read the indication value sent by the server. I am not even sure if my server is sending the indication value to the client upon service change. So, first I wanted to know how can I debug the indication value sent upon service change from server side and receive at client side, secondly, is my iphone mobile with above specs have the re-discovery mechanism upon reading indication value or the cache is not cleared and lastly will this service change re-discovery mechanism also works for android mobiles or is specific to selective ios mobiles. Please clarifies these things for me!

I have implemented the service in my server as mentioned in below github link: https://github.com/apache/mynewt-nimble/blob/debd4738ba0ec6e6645959a900a3dbce15710281/nimble/host/services/gatt/src/ble_svc_gatt.c#L60C13-L65C15

rahult-github commented 1 month ago

Hi @BestBot7 ,

  1. For debug logs :

For nrf side, you can opt for verbose mode logging that gives some information of information received For esp device side, you can enable Debug logs and see whether device side has sent information or not.

  1. For iOS cache. A simple test can be done. First pair the iphone with your device and check logs if service discovery was performed . Now disconnect and connect again. If iphone has cached services, it will not perform service discovery.

  2. The mentioned functionality is as per BLE spec, so applicable to all devices .

BestBot7 commented 1 month ago

Hi @rahult-github, I have enabled the verbose logs in nrf connect and subscribed the to the service changed service in the android BLE client app. When I change the service of the server in runtime, there is no indication value received. The problem still persists. Still not knowing how indications are not received on client side.

One more observation is that, in android mobile nrf connect app, when I select the "Refresh Services" option in the dropdown provided in the app, I observed the following in the logs as cache refreshed and re-discovering services. Yet the indication value is still not received!

image

rahult-github commented 1 month ago

Hi @BestBot7 ,

On server side, can you share your code changes where you have sent notification ? Please also share esp device side debug logs.

You can enable debug logs on esp device by following method:

Component config → Log output → Default log verbosity --> Set to Debug

Component config → Bluetooth → NimBLE Options → NimBLE Host log verbosity --> Set to Debug

BestBot7 commented 1 month ago

Hi @rahult-github, please find the debug logs from server side. Two BLE clients are connected to the server and in one client the service is changed after on-boarding the device and the indication is monitored in other client. service_changed_debug_logs.txt

rahult-github commented 1 month ago

Hi @BestBot7 ,

I saw the image on nrf , that you have uploaded. We do see "Cache refreshed" . This indicates nrfconnect app has done refetch of services. So what is not working in that case ?

I wrote a sample app change at my end to verify :

 case BLE_GAP_EVENT_SUBSCRIBE:
        printf("Forcing gatt change \n");
       ble_svc_gatt_changed(0x0000, 0xFFFF);   //example location
       return 0;
 }

After connection, i enabled indication on the service changed characteristic and i do see refetch of services happening. This is same to what you have uploaded too.

image

BestBot7 commented 1 month ago

Hi @rahult-github,

In the image I have uploaded, I manually clicked on the refresh services option provided by nrf connect app. I want that to happen automatically as soon as the indication is received on the mobile app. I have used the block of code which you suggested in the SUBSCRIBE event but still fails to indicate on the service. How did your client refresh the services? Did you manually clicked on the refresh services option as I did or the server indicated the service change and it did the re-discovery? Also specify which mobile you are testing this with.

rahult-github commented 1 month ago

How did your client refresh the services? Did you manually clicked on the refresh services option as I did or the server indicated the service change and it did the re-discovery?

No, this is automatic, the only activity that we need to perform is to subscribe, which is the requirement.

I have tested on multiple phones ( iOS 17.8.1 ) and Android phones. The nrf connect app version is fairly latest , version 4.28.1

So, the overall functioning is :

  1. Server has to expose the characteristic
  2. Client has to subscribe on the characteristic
  3. Server sends notification.
  4. Client when receives the notification has to perform operations as per their implementation.

May i know which phone you are using . We can try to check with same, if we have it at our end.

BestBot7 commented 1 month ago

I am using nrf connect version 4.28.1 in redmi note 11 pro android mobile. I am able to subscribe to the characteristics but the indication value is not displayed. Can you share me the characteristics part of code too. Just to check how are you implementing it in the server. Also you are saying "Server sends notification", are you notifying the service change or indicating? Please share you code snippet of characteristics implementation so that I will verify mine.

BestBot7 commented 1 month ago

Hi @rahult-github, can you share the characteristic implementation and the call back function used at your end?

rahult-github commented 1 month ago

Hi @BestBot7 , comment here has the changes i did and i used examples/provisioning/wifi_prov for testing purpose.

Reattaching the patch here for reference.

service_change.txt

BestBot7 commented 1 month ago

Hi @rahult-github, if the service change is indicated, will it change the services in all connected clients or only the specific client which is responsible for service change will have those changes?

rahult-github commented 1 month ago

Per spec, it is sent to all connected devices. The recipient has to have the intelligence whether to process it or drop it.

BestBot7 commented 3 weeks ago

Hi @rahult-github, The service change feature is now working! thanks for the support. The problem was that I have not used init api "ble_svc_gatt_init()" and now it is resolved. Now the issue is that I have to manually subscribe to the service changed characteristics otherwise it is not automatically subscribing. Is there a way to make some changes in the server side to allow automatic subscription to the characteristics by client?

Also upon service change I get an error saying connection parameters update failed as shown in the image below. What is that error and how to resolve that? Please help me in resolving these!

image

rahult-github commented 3 weeks ago

Is there a way to make some changes in the server side to allow automatic subscription to the characteristics by client?

No, because there is no such functionality mentioned in BLE spec. Client has to subscribe and only then server can send information to clients who are subscribed.

For the issue , wanted to know if you have any capability to capture over the air logs ? Any sniffer ?

BestBot7 commented 3 weeks ago

No, because there is no such functionality mentioned in BLE spec. Client has to subscribe and only then server can send information to clients who are subscribed.

Thanks for the support! really helped me a lot in fixing this!

For the issue , wanted to know if you have any capability to capture over the air logs ? Any sniffer ?

No there are such tools with me

rahult-github commented 3 weeks ago

Hi @BestBot7 , may i request you to please share debug enabled logs for esp device side. The error 35 seems to be specific to nrfConnect and hence not able to understand the failure.

BestBot7 commented 2 weeks ago

Hi @rahult-github, Sorry for the late response. Please find the server side debug logs as per your request.

refresh_char_bug.txt

Also let me know if there is any way where the service change characteristics works even without subscribing to it.

rahult-github commented 2 weeks ago

Hi @BestBot7 ,

Please find the server side debug logs as per your request.

So, actually i was requesting "debug enabled" logs for esp device side. The way to enable debug logs is as below, in case you are not already aware of :

`Component config → Log output → Default log verbosity --> Set to Debug

Component config → Bluetooth → NimBLE Options → NimBLE Host log verbosity --> Set to Debug `

if there is any way where the service change characteristics works even without subscribing to it.

No, because this is as mentioned in BLE specification.

Other way i can think of is that may be you can develop your own proprietory characteristic on which you send indication , but this will need changes even on client side ( i.e. both server and client side would need changes )

BestBot7 commented 2 weeks ago

Hi @rahult-github, Please find the attached debug logs. The service is changed from onboarding to session key service in the logs provided. Both server side and nimble side logs are enabled in debug mode. Please let me know if anything required. NimBLE_Debug_logs.txt __

rahult-github commented 2 weeks ago

Hi @BestBot7 ,

If we check the debug logs we see disconnect reason:

I (27645) [ICM BLE]: Line:515, ble_spp_server_gap_event, disconnect; conn_handle:1 reason=531 conn_dev_cnt:0

Here reason 531 implies remote device initiated disconnect.

If i check the snapshot of the nrfconnect, i see that some connection update procedure has failed. However , in debug logs, we don't see ESP device initiating any connection update.

I tried at my end again, but i don't see this behaviour.

have you made any changes in applicaiton side to update the connection parameters after connection is done ?