I have a ESP32-S3-DevKitC-1 Board and a NUKI FOB. The ESP32 works as NUKI Lock Server, I have already set the follow Services and Characterisits for ESP32 Sever, to let it wokr like a NUKI Lock. the Destination is to let the ESP32 NUKI Lock Server pair with a real NUKI FOB.
I have annouced and advertised the Server with “Keyturner Pairing Service” with Characteristic(and other all Services and Characteristics in my follow code)
can you give me a example or short explanation, how to creat key pair and enable pair mode on server side to pair with a real NUKI FOB, if I press NUKI FOB Buttom 5 second?
I have already written the follow code, to realize a simple Update for value1, value2, value3 in every Charateristic and it works. just like my question, I don’t know how can I go on for “Key Pairing” now… I have also read the document “Nuki Smart Lock API V2.1 16.03.2020”, the example about “Command usage” in the document seems what I need, but I don’t know to realize it in C or C++. there is an example " Smart Lock Simulator", it works as NUKI Lock Server and with key pair, but is in Java, it is not easy for me to use it…
I look forward to some help and feedback from you, thank you very much in Advance.
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include "HardwareSerial.h"
#include "Arduino.h"
BLEServer* pServer = NULL;
BLECharacteristic* pKeyturnerPairingGeneralDataInputOutputCharacteristic = NULL;
BLECharacteristic* pKeyturnerGeneralDataInputOutputCharacteristic = NULL;
BLECharacteristic* pKeyturnerUserSpecificDataInputOutputCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint32_t value1 = 0;
uint32_t value2 = 0;
uint32_t value3 = 0;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define KEYTURNER_INITIALIZATION_SERVICE_UUID "a92ee000-5501-11e4-916c-0800200c9a66"
#define KEYTURNER_PAIRING_SERVICE_UUID "a92ee100-5501-11e4-916c-0800200c9a66"
#define KEYTURNER_PAIRING_GENERAL_DATA_INPUT_OUTPUT_CHARACTERISTIC_UUID "a92ee101-5501-11e4-916c-0800200c9a66"
#define KEYTURNER_SERVICE_UUID "a92ee200-5501-11e4-916c-0800200c9a66"
#define KEYTURNER_GENERAL_DATA_INPUT_OUTPUT_CHARACTERISTIC_UUID "a92ee201-5501-11e4-916c-0800200c9a66"
#define KEYTURNER_UER_SPECIFIC_DATA_INPUT_OUTPUT_CHARACTERISTIC_UUID "a92ee202-5501-11e4-916c-0800200c9a66"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
void setup() {
Serial.begin(115200);
// Create the BLE Device
BLEDevice::init("ESP32");
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the Keyturner Initialization Service
BLEService *pKeyturnerInitializationService = pServer->createService(KEYTURNER_INITIALIZATION_SERVICE_UUID);
// Create the Keyturner Pairing Service
BLEService *pKeyturnerPairingService = pServer->createService(KEYTURNER_PAIRING_SERVICE_UUID);
// Create the Keyturner Service
BLEService *pKeyturnerService = pServer->createService(KEYTURNER_SERVICE_UUID);
// Create a Keyturner Pairing General Data Input Output Characteristic
pKeyturnerPairingGeneralDataInputOutputCharacteristic = pKeyturnerPairingService->createCharacteristic(
KEYTURNER_PAIRING_GENERAL_DATA_INPUT_OUTPUT_CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// Create a Keyturner General Data Input Output Characteristic
pKeyturnerGeneralDataInputOutputCharacteristic = pKeyturnerService->createCharacteristic(
KEYTURNER_GENERAL_DATA_INPUT_OUTPUT_CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// Create a Keyturner User Specific Data Input Output Characteristic
pKeyturnerUserSpecificDataInputOutputCharacteristic = pKeyturnerService->createCharacteristic(
KEYTURNER_UER_SPECIFIC_DATA_INPUT_OUTPUT_CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
// Create a BLE Descriptor
pKeyturnerPairingGeneralDataInputOutputCharacteristic->addDescriptor(new BLE2902());
pKeyturnerGeneralDataInputOutputCharacteristic->addDescriptor(new BLE2902());
pKeyturnerUserSpecificDataInputOutputCharacteristic->addDescriptor(new BLE2902());
// Start the service
pKeyturnerInitializationService->start();
pKeyturnerPairingService->start();
pKeyturnerService->start();
// Start advertising
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(KEYTURNER_INITIALIZATION_SERVICE_UUID);
pAdvertising->addServiceUUID(KEYTURNER_PAIRING_SERVICE_UUID);
pAdvertising->addServiceUUID(KEYTURNER_SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
BLEDevice::startAdvertising();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
// notify changed value
if (deviceConnected) {
pKeyturnerPairingGeneralDataInputOutputCharacteristic->setValue((uint8_t*)&value1, 4);
pKeyturnerPairingGeneralDataInputOutputCharacteristic->notify();
value1++;
pKeyturnerGeneralDataInputOutputCharacteristic->setValue((uint8_t*)&value2, 4);
pKeyturnerGeneralDataInputOutputCharacteristic->notify();
value2++;
pKeyturnerUserSpecificDataInputOutputCharacteristic->setValue((uint8_t*)&value3, 4);
pKeyturnerUserSpecificDataInputOutputCharacteristic->notify();
value3++;
delay(3); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}