I'm reading through as much as I can on the theory. From what I can tell ... the protocol says the following:
A BLE Server can transmit either notifications or indications to a connected partner (a BLE Client).
A notification is a message sent from the BLE Server to the client with no expected acknowledgement.
An indication is a message sent from the BLE Server to the client with an an expectation of acknowledgement.
(I'll just talk about notifications from now on and leave indications for another story).
When a server "defines" a characteristic in a service, that characteristic contains "characteristic properties" which include whether or not the characteristic even "supports" notifications. This can be read by the client so that the client can the learn whether or not there will *ever* be notifications on that characteristic.
If the server owned characteristic *does* say that it supports notification, then that characteristic *must* have a BLE descriptor with UUID 0x2902 (Client Characteristic Configuration or CCC). The is a "writable" descriptor. That means that a BLE client can gain access to it and change its value remotely (remember, the value is housed on the BLE Server associated with the descriptor associated with the characteristic associated with the service). There is a "bit" within the descriptor (0x2902) which if set to 1, means notifications are enabled and if set to 0, means notifications are disabled.
And it is here things get a little fuzzy. My comprehension of this works as follows ...
Imagine a BLE Server that has a sensor attached to it (for example, a temperature sensor). Rather than the client poll the characteristic to get the temperature, what we want to have happen is that the server will detect a change in temperature and then push (notify) the client only when the temperature changes. Sounds good. But rather than the server unilaterally transmitting the sensor data when ever it detects a change, my belief is that the server wants some form of "assurance" that the client at the other end of the connection actually wants that data. Think for example of a BLE server with many sensors attached to it ... if it was internally monitoring those sensors and publishing them merrily down the radio pipe to a client, that would be a lot of expensive radio transmission when *maybe* the client is only interested in some sensor values and not others.
And here is where the parts come together. It is my understanding that the client should "inform" (register?) the BLE server that for a given characteristic, it is actively interested in receiving notifications. It does this by making a write request (from the BLE Client to the BLE Server) to switch on the bit that enables BLE notifications in the 0x2902 descriptor. When the server now detects a change in temperature it *first* examines the bit in the 0x2902 descriptor to ascertain whether the client wants a notification and, only if it is true, will the server send a notification.
In pseudo code it is similar to:
Code: Select all
while(true) {
if (value of temperature has changed) {
if (Notifications enabled bit of 0x2902 descriptor is true) {
transmit a Notification for this characteristic with new sensor data;
}
}
}
With this *theory*, now let us look at the ESP32 API called "esp_ble_gattc_register_for_notify". This is a BLE client API ... and it takes a characteristic ID/handle as a parameter. But what does it actually do?
My guess is that it connects to the BLE Server, finds the characteristic within the target service and then looks for descriptor 0x2902. It then sets the "Notifications enabled" bit to be true. This would then be the "indication" to the BLE server that should it determine that it is time that it "could" send a notification that it "should" (because the information has been requested).
Unfortunately ... there is but one fault in this story. Using the tooling / techniques that I know about, after executing an "esp_ble_gattc_register_for_notify", I am *not* seeing the "notifications enabled" bit being set to true in the BLE Server (I am testing with nRF Connect and working with other BLE devices that should start notifying after this call also are not).
This means that either I am mis-understanding the theory, mis-understanding the protocols (both of which are very possible) ... or don't understand what the ESP32 ESP-IDF is "supposed to do" or is "actually doing" .... alternatively ... I do understand it correctly ... and it just "isn't" doing it because of a possible breakage (anything is possible ... but I usually lean to a failure in my understanding before saying "its broke").
Hence this post ...