-
Notifications
You must be signed in to change notification settings - Fork 7.6k
BLE Client Characteristic Configuration descriptor (BLE2902) value is not resetting to default (00 00) on connection #6863
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
You can always set it to zero when the BLE server finds out that the client has disconnected (in a callback). For that you can do something like this: BLE2902 *ble2902 = new BLE2902();
....
ble2902->setNotifications(false); // or true to turn it on Check some the BLE2902 API at https://github.com/espressif/arduino-esp32/blob/master/libraries/BLE/src/BLE2902.h |
@SuGlider |
Could you please provide minimum example code that demonstrates the issue, for both master and slave. I'll test it and verify/fix this issue. |
@SuGlider https://github.com/SuperTankMan/Issue-code Issue #6863 - As it is just compile and see that fit the LED does not flash. Then use somethign like nRF connect or BLE Scanner mobile app to connect, select service 0x1700 and register the notification. Once the counter starts updating in the characteristics values and LED starts flashing disconnect without deregistering notifications. Then connect again and you'll see that the counter will continue counting and LED flashing without reregistering for the notifications(if the notifications and indications were set to default 0x0000 then this would not happen) also you can read the BLE2902 values using nRF or BLE scanner. //((BLE2902*)myBLE2902)->setNotifications(false); //code file starts here... #define LED_BUILTIN 26 /* Define Service */ BLEDescriptor *myBLE2902 = new BLE2902(); uint8_t counter = 1; BLECharacteristic counterCharacteristic class MyServerCallbacks : public BLEServerCallbacks void setup() // Serial.begin(115200); //Create and name the BLE device /* Create the BLE server */ /* Create service on the server */ /* Add characteristic to the service */ /* Configure advertising with the service to advertise */ // Start the service // Start the Server/Advertising Serial.println("Waiting for a Client to connect..."); void loop() if (!deviceConnected) |
The counter also stops and starts whenever pressing the Changing CCCD in the server doesn't affect the client because in BLE the client is who should control CCCD. Therefore calling I think that the explanation above may cover all the issues you have reported. |
I am not convinced about this the device stops advertising as soon as its connected and when callback onDisconnect(BLEServer* MyServer) is called the advertising starts again when disconnected hence it is calling onDisconnect(BLEServer* MyServer). Also the fact that when the line below//((BLE2902*)myBLE2902)->setNotifications(false); is uncommented then the Server stops sending notifications it means working I have also moved this line to the onDisconnect(BLEServer* MyServer) and that too works.
Sure it is able to stop however it takes two registration of notification from the client to enable notification in stead of the one and when the Client reads the status of the BLE2902 i.e. registation and notification status it does not read the correct value.
Sure Client can control but its getting wrong information when reading in the case when setNotification(false) is called() and this not acceptable in the sense that the Bluetooth specification clearly states the behaviour to set its self to default as detailed and reference in the issue.
Sure and it look like that is the case however its not helpful to the Client when he needs to know(by reading BLE2902) the status of the registration of notification as he gets false information.
Sure persistence can be achieved as you stated however that is not the issue, the issue is that it's not adhering to the Bluetooth spec. and not updating the BLE2902 when setNotification(fbool) is called
While I appreciate your assistance and help I do not think this issue is resolved I do think its a bug and does not adhere to the specification and hence both the issue still stands. |
Issue confirmed. There are actually two issues: These functionalities need to be implemented in BLE Library: |
Hi @SuGlider I am not so sure if issue: L185-L194(ESP32 BLE Server doesn't send back Descriptor when read is requested by BLE Client.) is completely true. I have done this experiment where I use one client to connect then register for notifications then I read the value of the BLE2902 descriptor and it reads value correctly as expected. I have also tried another experiment where a client connects then registers for notifications and then disconnects. I then use another client device to connect and read the BLE2902 descriptor and then too again is read correctly. What is not happening is that when I internally setNotifications(true or false) and then read the BLE2902 then it does not read correctly! hence not sure of your description of the issue. Also there is the issue that when server is disconnected from an unbonded/unpaired device the BLE2902 is not reset to its default value of 0x0000. I am also not sure about L54-L58(ESP32 BLE Client doesn't receive Descriptor data when it is sent from BLE Server) I have not done this experiment with ESP32 being the Client so do not know. Please clarify to me if I am missing something and also that the implanted cure will resolve both my issues? Thank you for your assistance and sorry if I have not understood your cure to be implemented. |
Although there is no Code in L185-L194 of BLE Server to send back Descriptor information, it seems that it would no be necessary anyway because BLE Client send a Read Descriptor UUID Request with the Frame Fields Talking about the issue here posted, reseting to (00 00), it can be done, as said, by software. |
By default, when BLE2902 is created in the Server, it has Notification ON, so if you need the Client to start with it as OFF, turn it off before Advertising. The above statement is not true the extracted constructor code from BLE2902 clearly sets it notifications and indications to off. i.e. 0x0000 so it is not creating the BLE2902 with Notifications ON! BLE2902::BLE2902() : BLEDescriptor(BLEUUID((uint16_t) 0x2902)) { I have done a lot of investigation in this and its not working the way it should I do request you understand the issue and test thoroughly as I have done. Please note the code I have send is a simplified version for people to undestabnd the issue but I have a larger project that I am working on. As I said when I setNotification(false) it does not get reflected to the client when it is read by the client. even when you use one client to register for notification and then disconnect and connect using another client, in case they are caching the value, even then the read value by the other client is the same as the previous client! how can this be unless they are reading and being sent the value? I think this is a bug and the server is sending a value as you can see in the logs of nRF but its sending the incorrect value. its as if the setNotifications(bool) and getNotifications() use one variable and the when Client reads the BLE2902 it send another different variable which the server reads and writes. |
What is exactly the BLE Client you are using in the testing? |
We have our own Client coded in Kotlin by another team. I use nRF connect on a tablet to act as a client and ESP32 as a server. but I have also used BLE scanner and they both DO NOT get the correct notification value (i.e BLE2902) on connect (i.e 0x0000) or when I have setNotification(false) before advertising as you suggested. As I mentioned before its as if the internal BLE2902 is not sent when I setNotification(false) (both nRF connect and BLE scanner is available from Android play store) |
Ok. That means you are using an Android BLE Client. You can verify it by just adding a |
@SuGlider void onDisconnect(BLEServer* MyServer) Result log: rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) |
Ok. For some reason my nRF Connect APP doesn't send anything when I press disconnect button. Anyway, I turn off Bluetooth radio in Android and get the same log output as you reported. About Notification, the issue is because Android and iOS use to cache all services, characteristics and descriptors. When nRF APP reconnects to ESP32 BLE Server, it doesn't refresh its cache. In order to force such cache update, it is necessary to use Generic Attribute 0x1801 and Characteristic Service Changed 0x2A05 to indicate it to the client. |
Hi @SuGlider
|
Issue confirmed. I'll send a fix soon. |
Please apply the fix #6919 to your local machine. #include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#define LED_BUILTIN 2
/* Define Service */
//Custome service UUID
#define serviceID BLEUUID((uint16_t)0x1700)
BLE2902 *myBLE2902 = new BLE2902();
bool deviceConnected = false;
uint8_t counter = 1;
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 1000; // interval at which to blink (milliseconds)
BLECharacteristic counterCharacteristic
{
BLEUUID((uint16_t)0x1A00),
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_NOTIFY
};
class MyServerCallbacks : public BLEServerCallbacks
{
void onConnect(BLEServer* MyServer)
{
deviceConnected = true;
}
void onDisconnect(BLEServer* MyServer)
{
//Not connected so reset Notifications
myBLE2902->setNotifications(false);
deviceConnected = false;
MyServer->getAdvertising()->start();
}
};
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
// Serial.begin(115200);
//Create and name the BLE device
BLEDevice::init("ESP32BLETest");
/* Create the BLE server */
BLEServer *MyServer = BLEDevice::createServer();
MyServer->setCallbacks(new MyServerCallbacks()); // Set the function that handles Server Callbacks
/* Create service on the server */
//BLEService *MyService = MyServer->createService(BLEUUID((uint16_t)0x1700)); // A random ID has been selected
BLEService *MyService = MyServer->createService(serviceID); // A random ID has been selected
/* Add characteristic to the service */
MyService->addCharacteristic(&counterCharacteristic);
counterCharacteristic.addDescriptor(myBLE2902);
counterCharacteristic.setValue(&counter, 2);
/* Configure advertising with the service to advertise */
MyServer->getAdvertising()->addServiceUUID(serviceID);
// Start the service
MyService->start();
// Start the Server/Advertising
MyServer->getAdvertising()->start();
Serial.println("Waiting for a Client to connect...");
}
void loop()
{
digitalWrite(LED_BUILTIN, HIGH);
if (deviceConnected)
{
//if registered for Notification then flash LED and send counter value to Client by notification
if (myBLE2902->getNotifications())
{
//loop to blink without delay
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval)
{
// save the last time you blinked the LED
previousMillis = currentMillis;
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
counter++;
counterCharacteristic.setValue(&counter, 1);
counterCharacteristic.notify();
}
}
}
}
|
Description of Change This PR fixes an issue related to BLE Server and Descriptors. The issue: If the BLE Server code changes its own descriptors, it is not reflected in the GATTS database. BLE2902 CCCD also didn't reflect any changes to the GATTS database. Because of this issue, the client could never read the real Descriptor values from the remote Server. Tests scenarios Tested with ESP32. Related links Fixes #6863 Fixes #6868
Board
az-delivery-devkit-v4
Device Description
ESP32 with stepper motor and few basic level sensors.
Hardware Configuration
Not relevant
Version
v2.0.2
IDE Name
Arduino IDE and PlatformIO
Operating System
All.
Flash frequency
80-240Mhz
PSRAM enabled
no
Upload speed
115200
Description
Hi All, this is my first discussion post so please excuse my manners :p
Recently I have been working on ESP32 BLE where the server sets up a service in which the attributes are read, Write, Notify. hence a BLE2902 is added to the characteristics. Once the client registers for the notification and then after a few notifications being received the client disconnect from the server without disabling notifications.
I have noticed that when the client makes connection again (without being bonded) the notification is still enabled! however the Bluetooth specifications specifically state that it should be reset to default value of notifications and Indications i.e disabled when not bonded. Anyone can test this using nRF connect and a standard service or useing BLE_notify.ino from the examples which has characteristics with notification.
Test procedure:
1.0 Connect to the device.
2.0 Enable Notification on a characteristic.
3.0 Disconnect from the device but not reset.
4.0 Connect to the device without power cycle or rest.
5.0 Check the status of the notification by reading value of BLE2902 it should reset to 00 00 or notification and indication disabled (see ref below) but it does not.
Has anyone noticed this and if so is this how ESP32 BLE is supposed to behave? or is it a bug or an issue?
TankMan-
References:
BLUETOOTH SPECIFICATION Version 4.2 [Vol 0]
3.3.3.3 Client Characteristic Configuration
The Client Characteristic Configuration declaration is an optional characteristic
descriptor that defines how the characteristic may be configured by a specific
client. The Client Characteristic Configuration descriptor value shall be
persistent across connections for bonded devices. The Client Characteristic
Configuration descriptor value shall be set to the default value at each
connection with non-bonded devices. The characteristic descriptor value is a bit
field. When a bit is set, that action shall be enabled, otherwise it will not be
used. The Client Characteristic Configuration descriptor may occur in any
position within the characteristic definition after the Characteristic Value. Only
one Client Characteristic Configuration declaration shall exist in a
characteristic definition.
Extracted from further down the spec. near Table 3.11 in the specification
Configuration Value Description
Notification 0x0001 The Characteristic Value shall be notified. This value can only be set if the characteristic’s property has the notify bit set.
Indication 0x0002 The Characteristic Value shall be indicated. This value can only be set if the characteristic’s property has the indicate bit set.
Reserved for
Future Use
The following Client Characteristic Configuration bits are defined:
The default value for the Client Characteristic Configuration descriptor value
shall be 0x0000.
Sketch
Use the BLE_notify.ino example and follow the instructions above
Debug Message
Other Steps to Reproduce
Use nRF connect or similar to register for notification or read BLE2902 values.
I have checked existing issues, online documentation and the Troubleshooting Guide
The text was updated successfully, but these errors were encountered: