Hello, first excuse me for my level of English.
I have modified the server example to add some parts of code and when I compile and load it, the code hangs and I can't find an explanation.
The code is composed of a service with no features, a service with two features, and a full battery service.
When I compile and send in the ble monitor that I use, all the services appear and I can request the characteristics of the service that has both characteristics, but if I try to subscribe to the battery notification service 1 does not subscribe and 2 is blocked and no longer It lets me access the features of the other service. In the arduino ide serial monitor I don't see the microprocessor reset so I'm not experiencing an overflow of some kind (or so I think).
I can be working indefinitely reading the two characteristics without problem, until I touch the battery.
The most curious thing is that if I remove one of the service that has two characteristics, I can now connect to the notification service without problem and the system does not hang.
I've tried with an esp32s and a wroom32 in case it was a compilation problem but it didn't solve the problem so I guess I'm doing something wrong in the code.
Any idea what it could be?
#include <NimBLEDevice.h>
static NimBLEServer *pServer;
/** None of these are required as they will be handled by the library with defaults. **
** Remove as you see fit for your needs */
class ServerCallbacks: public NimBLEServerCallbacks {
void onConnect(NimBLEServer* pServer) {
Serial.println("Client connected");
Serial.println("Multi-connect support: start advertising");
NimBLEDevice::startAdvertising();
};
/** Alternative onConnect() method to extract details of the connection.
* See: src/ble_gap.h for the details of the ble_gap_conn_desc struct.
*/
void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
Serial.print("Client address: ");
Serial.println(NimBLEAddress(desc->peer_ota_addr).toString().c_str());
pServer->updateConnParams(desc->conn_handle, 24, 48, 0, 60);
};
void onDisconnect(NimBLEServer* pServer) {
Serial.println("Client disconnected - start advertising");
NimBLEDevice::startAdvertising();
};
void onMTUChange(uint16_t MTU, ble_gap_conn_desc* desc) {
Serial.printf("MTU updated: %u for connection ID: %u\n", MTU, desc->conn_handle);
};
/********************* Security handled here **********************
****** Note: these are the same return values as defaults ********/
uint32_t onPassKeyRequest(){
Serial.println("Server Passkey Request");
/** This should return a random 6 digit number for security
* or make your own static passkey as done here.
*/
return 123456;
};
bool onConfirmPIN(uint32_t pass_key){
Serial.print("The passkey YES/NO number: ");Serial.println(pass_key);
/** Return false if passkeys don't match. */
return true;
};
void onAuthenticationComplete(ble_gap_conn_desc* desc){
/** Check that encryption was successful, if not we disconnect the client */
if(!desc->sec_state.encrypted) {
NimBLEDevice::getServer()->disconnect(desc->conn_handle);
Serial.println("Encrypt connection failed - disconnecting client");
return;
}
Serial.println("Starting BLE work!");
};
};
/** Handler class for characteristic actions */
class CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
void onRead(NimBLECharacteristic* pCharacteristic){
Serial.print(pCharacteristic->getUUID().toString().c_str());
Serial.print(": onRead(), value: ");
Serial.println(pCharacteristic->getValue().c_str());
};
void onWrite(NimBLECharacteristic* pCharacteristic) {
Serial.print(pCharacteristic->getUUID().toString().c_str());
Serial.print(": onWrite(), value: ");
Serial.println(pCharacteristic->getValue().c_str());
};
/** Called before notification or indication is sent,
* the value can be changed here before sending if desired.
*/
void onNotify(NimBLECharacteristic* pCharacteristic) {
Serial.println("Sending notification to clients");
};
/** The status returned in status is defined in NimBLECharacteristic.h.
* The value returned in code is the NimBLE host return code.
*/
void onStatus(NimBLECharacteristic* pCharacteristic, Status status, int code) {
String str = ("Notification/Indication status code: ");
str += status;
str += ", return code: ";
str += code;
str += ", ";
str += NimBLEUtils::returnCodeToString(code);
Serial.println(str);
};
void onSubscribe(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc, uint16_t subValue) {
Serial.println("OnSubscribe detected");
String str = "Client ID: ";
str += desc->conn_handle;
str += " Address: ";
str += std::string(NimBLEAddress(desc->peer_ota_addr)).c_str();
if(subValue == 0) {
str += " Unsubscribed to ";
}else if(subValue == 1) {
str += " Subscribed to notfications for ";
} else if(subValue == 2) {
str += " Subscribed to indications for ";
} else if(subValue == 3) {
str += " Subscribed to notifications and indications for ";
}
str += std::string(pCharacteristic->getUUID()).c_str();
Serial.println(str);
};
};
/** Handler class for descriptor actions */
class DescriptorCallbacks : public NimBLEDescriptorCallbacks {
void onWrite(NimBLEDescriptor* pDescriptor) {
std::string dscVal = pDescriptor->getValue();
Serial.print("Descriptor witten value:");
Serial.println(dscVal.c_str());
};
void onRead(NimBLEDescriptor* pDescriptor) {
Serial.print(pDescriptor->getUUID().toString().c_str());
Serial.println(" Descriptor read");
};
};
/** Define callback instances globally to use for multiple Charateristics \ Descriptors */
static DescriptorCallbacks dscCallbacks;
static CharacteristicCallbacks chrCallbacks;
void setup() {
Serial.begin(115200);
Serial.println("Starting NimBLE Server in BlazePodTwo proyect");
NimBLEDevice::init("MyBle");
/** Optional: set the transmit power, default is 3db */
#ifdef ESP_PLATFORM
NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
#else
NimBLEDevice::setPower(9); /** +9db */
#endif
NimBLEDevice::setSecurityAuth(/*BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM |*/ BLE_SM_PAIR_AUTHREQ_SC);
pServer = NimBLEDevice::createServer();
pServer->setCallbacks(new ServerCallbacks());
//NimBLEBatteryService batteryService("0000180F-0000-1000-8000-00805F9B34FB");
//NimBLEBatteryLevelCharacteristic batteryLevel("00002a19-0000-1000-8000-00805f9b34fb");
NimBLEService* pParcelService = pServer->createService("10c323ba-4008-12a3-bbbb-0908ea180dd6");
// DeviceInfoService
#define SERIAL_NUMBER "56982"
#define FIRMWARE_REVISION "1.4.22"
NimBLEService* pDeviceInfoService = pServer->createService("0000180A-0000-1000-8000-0000000000AA");
//DeviceInfoService-Serial Number
NimBLECharacteristic* pSerialNumberCharacteristic = pDeviceInfoService->createCharacteristic(
""00002A25-0000-1000-8000-0000000000aa",
NIMBLE_PROPERTY::READ
);
pSerialNumberCharacteristic->setCallbacks(&chrCallbacks);
pSerialNumberCharacteristic->setValue(SERIAL_NUMBER);
NimBLECharacteristic* pFirmwareRevisionCharacteristic = pDeviceInfoService->createCharacteristic(
"00002A26-0000-1000-8000-0000000000aa",
NIMBLE_PROPERTY::READ
);
pFirmwareRevisionCharacteristic->setCallbacks(&chrCallbacks);
pFirmwareRevisionCharacteristic->setValue(FIRMWARE_REVISION);
/*********************************** BatteryService **************************************/
//BatteryService
NimBLEService* pBatteryService = pServer->createService("0000180F-0000-1000-8000-0000000000aa");
//BatteryService-BatteryLevel
NimBLECharacteristic* pBatteryLevelCharacteristic = pBatteryService->createCharacteristic(
"00002A19-0000-1000-8000-0000000000aa",
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::NOTIFY
);
pBatteryLevelCharacteristic->setCallbacks(&chrCallbacks);
NimBLE2904* pBatteryLevelDescriptor = (NimBLE2904*)pBatteryLevelCharacteristic->createDescriptor("2904");
pBatteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UTF8);
pBatteryLevelDescriptor->setNamespace(1);
pBatteryLevelDescriptor->setUnit(0x27ad);
pBatteryLevelDescriptor->setCallbacks(&dscCallbacks);
uint8_t batteryLevel = 88; // nivel de batería
pBatteryLevelCharacteristic->setValue(&batteryLevel, 1);
pParcelService->start();
pDeviceInfoService->start();
pBatteryService->start();
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->addServiceUUID(pParcelService->getUUID());
pAdvertising->addServiceUUID(pDeviceInfoService->getUUID());
pAdvertising->addServiceUUID(pBatteryService->getUUID());
pAdvertising->setScanResponse(true);
pAdvertising->setAppearance(0x0080);
pAdvertising->start();
Serial.println("Advertising Started");
}
void loop() {
/* batteryLevel = 98; // nivel de batería
pBatteryLevelCharacteristic->setCallbacks(&chrCallbacks);
pBatteryLevelCharacteristic->setValue(&batteryLevel, 1); // actualiza el valor de la característica
pBatteryLevelCharacteristic->notify(); // notifica al cliente que el valor ha cambiado
delay(5000);
*/
}
Hello, first excuse me for my level of English. I have modified the server example to add some parts of code and when I compile and load it, the code hangs and I can't find an explanation. The code is composed of a service with no features, a service with two features, and a full battery service. When I compile and send in the ble monitor that I use, all the services appear and I can request the characteristics of the service that has both characteristics, but if I try to subscribe to the battery notification service 1 does not subscribe and 2 is blocked and no longer It lets me access the features of the other service. In the arduino ide serial monitor I don't see the microprocessor reset so I'm not experiencing an overflow of some kind (or so I think). I can be working indefinitely reading the two characteristics without problem, until I touch the battery. The most curious thing is that if I remove one of the service that has two characteristics, I can now connect to the notification service without problem and the system does not hang. I've tried with an esp32s and a wroom32 in case it was a compilation problem but it didn't solve the problem so I guess I'm doing something wrong in the code. Any idea what it could be?