Hi,
I have started writing an arduino library for use with an ESP32 to connect/configure a Nuki smart lock 2.0 via BLE.
I intend to make this open source on GIT once it is working, for others to use and improve…
I have started with the BLE API (which looks really well documented btw) but I allready get stuck at the first part connecting.
I wrote my own code but as it is not working I was looking for a fix and came across the code in this post:
It seems I get a timeout on the first step; connect BLE to Nuki (pClient->connect(myNukiAddr);).
This happens after 30 seconds, which I suspect is initiated by the Nuki as I see the same happening in NRFconnect.
It looks a bit like the ESP32 tries to establish a connection but the Nuki does not respond…? And the ESP BLE connect needs to finish before you can start registering on chars and sending the messages…
Any help is appreciated.
This is the code I used (as allready present in this topic, only changed the BLE address)
/**
* A BLE client example that is rich in capabilities.
* There is a lot new capabilities implemented.
* author unknown
* updated by chegewara
*/
#include "BLEDevice.h"
#include "esp_log.h"
#include "Arduino.h"
//#include "BLEScan.h"
// The remote service we wish to connect to.
static BLEUUID serviceUUID("a92ee100-5501-11e4-916c-0800200c9a66");//Pairing service
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID("a92ee101-5501-11e4-916c-0800200c9a66");//Characteristic of pairing service
//std::vector<uint8_t> response(200);
static boolean connected = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
uint8_t arrayFV[] = {0x01,0x00,0x03,0x00,0x27,0xA7}; //"0x0100030027A7";//first value to send as an array of byte to initiate Nuki Pairing
void debug_dump_binary(const void* buffer, size_t size)
{
for(size_t i = 0; i < size; ++i)
{
if(i > 0 && (i % 8) == 0)
{
Serial.println("");
}
Serial.printf("%0x ", ((const uint8_t*) buffer)[i]);
}
}
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
Serial.print("******************** Notify callback for characteristic ");
Serial.println(pBLERemoteCharacteristic->getUUID().toString().c_str());
Serial.print(" of data length ");
Serial.println(length);
Serial.print("data: ");
//fw: don't print this directly. the value is binary, not a 0-terminated string
//Serial.println((char*)pData);
debug_dump_binary(pData, length);
// for(int i= 0;i<length;i++) response.push_back(*pData++);
} // end notifyCallback
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
}
};
bool connectToServer() {
Serial.print("Forming a connection to ");
std::string myNukiAddr="54:d2:72:4F:98:48";
BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
Serial.print(" Essai de connexion à Nuki");
pClient->connect(myNukiAddr); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
Serial.println(" - Connected to server");
delay(100);
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our characteristic");
Serial.print("CanRead : ");
Serial.println(pRemoteCharacteristic->canRead());
Serial.print("CanWrite : ");
Serial.println(pRemoteCharacteristic->canWrite());
Serial.print("CanNotify : ");
Serial.println(pRemoteCharacteristic->canNotify());
Serial.print("CanIndicate : ");
Serial.println(pRemoteCharacteristic->canIndicate());
connected = true;
Serial.print("connected : ");
Serial.println(connected);
return connected;
}
void setup() {
//esp_log_level_set("*", ESP_LOG_DEBUG);
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
if (connectToServer()) {
Serial.println("We are now connected to the BLE Server.");
} else {
Serial.println("We have failed to connect to the server; there is nothin more we will do.");
}
//register for indication
//fw: don't need this. this is done by registerForNotify()
//const uint8_t indicationOn[] = {0x2,0x0};
//pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)indicationOn,2,true);
pRemoteCharacteristic->registerForNotify(notifyCallback, false); //false = indication, true = notification
delay(100);
//write Value
if(pRemoteCharacteristic->canWrite()) {
//fw: and here's your problem. you were sending the first byte only (writeValue(arrayFV, 1)
pRemoteCharacteristic->writeValue(arrayFV, sizeof(arrayFV), true);
delay(50);
}
std::string value = pRemoteCharacteristic->readValue();
Serial.print("The characteristic value was: ");
Serial.println(value.c_str());
} // End of setup
// This is the Arduino main loop function.
void loop() {
//fw: I don't think you should loop here. loop() is looping anyways
Serial.println("debut loop...");
if (connected) {
Serial.println("Still connected, loop");
// Read the value of the characteristic.
std::string value = pRemoteCharacteristic->readValue();
Serial.print("The characteristic value was: ");
Serial.println(value.c_str());
delay(1000); // Delay between loops.
}
else {
Serial.println("not connected");
}
} // End of loop
This is the output where you see I get a onDisconnect:
Starting Arduino BLE Client application...
Forming a connection to - Created client
Essai de connexion à Nuki[D][BLEClient.cpp:96] connect(): >> connect(54:d2:72:4f:98:48)
[D][BLEDevice.cpp:593] addPeerDevice(): add conn_id: 0, GATT role: client
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLEClient.cpp:158] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLEClient.cpp:158] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
onDisconnect
- Connected to server
[I][BLEDevice.cpp:604] removePeerDevice(): remove: 0, GATT role client
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLEDevice.cpp:148] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... Unknown