I am enjoying round with this library and studying via the Apple Notification Middle Service(ANCS) however nonetheless have a tough time getting message and title of an iOs notification forwarded to my esp32 board and output them to the Serial Monitor inside Arduino Studio. With this code, I can pair my iPhone with the esp32 board and when notifications get ship over however all I received is the class like this:
20:01:50.225 -> ********************
20:01:50.225 -> **Machine related**
20:01:50.225 -> 30:9a:77:**:**:**
20:01:50.225 -> ********************
20:01:53.567 -> New notification!
20:01:53.567 -> Class: Information
Might somebody inform me what am I do flawed with this code?
(Arduino_ESP32_ANCS.ino, the Job.h and Job.cpp recordsdata can be found on github)
P.S: I take advantage of the default “Shortcuts” app on iPhone to set off faux notification to check if anybody is thinking about how one can have notifications to check.
// Authentic: https://github.com/S-March/esp32_ANCS
// mounted for Arduino15/packages/esp32/{hardware}/esp32/1.0.3
#embody <Arduino.h>
#embody "BLEDevice.h"
#embody "BLEServer.h"
#embody "BLEClient.h"
#embody "BLEUtils.h"
#embody "BLE2902.h"
#embody <esp_log.h>
#embody <esp_bt_main.h>
#embody <string>
#embody "Job.h"
#embody <sys/time.h>
#embody <time.h>
#embody "sdkconfig.h"
static char LOG_TAG[] = "SampleServer";
static BLEUUID ancsServiceUUID("7905F431-B5CE-4E99-A40F-4B1E122D00D0");
static BLEUUID notificationSourceCharacteristicUUID("9FBF120D-6301-42D9-8C58-25E699A21DBD");
static BLEUUID controlPointCharacteristicUUID("69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9");
static BLEUUID dataSourceCharacteristicUUID("22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB");
BLERemoteCharacteristic* pControlPointCharacteristic;
class MySecurity : public BLESecurityCallbacks {
uint32_t onPassKeyRequest(){
ESP_LOGI(LOG_TAG, "PassKeyRequest");
return 123456; // Returning a default passkey
}
void onPassKeyNotify(uint32_t pass_key){
ESP_LOGI(LOG_TAG, "On passkey Notify quantity:%d", pass_key);
}
bool onSecurityRequest(){
ESP_LOGI(LOG_TAG, "On Safety Request");
return true;
}
bool onConfirmPIN(uint32_t pin){
ESP_LOGI(LOG_TAG, "On Verify Pin Request with pin: %d", pin);
return true; // It's best to return true to substantiate the pin
}
void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
ESP_LOGI(LOG_TAG, "Beginning BLE work!");
if(cmpl.success){
uint16_t size;
esp_ble_gap_get_whitelist_size(&size);
ESP_LOGD(LOG_TAG, "dimension: %d", size);
}
}
};
static void dataSourceNotifyCallback(
BLERemoteCharacteristic* pDataSourceCharacteristic,
uint8_t* pData,
size_t size,
bool isNotify) {
Serial.print("Notify callback for attribute ");
Serial.print(pDataSourceCharacteristic->getUUID().toString().c_str());
Serial.print(" of information size ");
Serial.println(size);
// Parse the response
size_t index = 0;
uint8_t commandID = pData[index++];
uint32_t notificationUID = pData[index++] | (pData[index++] << 8) | (pData[index++] << 16) | (pData[index++] << 24);
whereas (index < size) {
uint8_t attributeID = pData[index++];
uint16_t attributeLength = pData[index++] | (pData[index++] << 8);
if (attributeID == 1) { // Title
Serial.print("Title: ");
} else if (attributeID == 2) { // Message
Serial.print("Message: ");
} else if (attributeID == 3) { // App Identifier
Serial.print("App Identifier: ");
}
for (uint16_t i = 0; i < attributeLength; i++) {
Serial.print((char)pData[index + i]);
}
Serial.println();
index += attributeLength;
}
}
static void NotificationSourceNotifyCallback(
BLERemoteCharacteristic* pNotificationSourceCharacteristic,
uint8_t* pData,
size_t size,
bool isNotify) {
if (pData[0] == 0) {
Serial.println("New notification!");
Serial.print(" ");
change (pData[2]) {
case 0: Serial.println("Class: Different"); break;
case 1: Serial.println("Class: Incoming name"); break;
case 2: Serial.println("Class: Missed name"); break;
case 3: Serial.println("Class: Voicemail"); break;
case 4: Serial.println("Class: Social"); break;
case 5: Serial.println("Class: Schedule"); break;
case 6: Serial.println("Class: Electronic mail"); break;
case 7: Serial.println("Class: Information"); break;
case 8: Serial.println("Class: Well being"); break;
case 9: Serial.println("Class: Enterprise"); break;
case 10: Serial.println("Class: Location"); break;
case 11: Serial.println("Class: Leisure"); break;
default: break;
}
// Name the perform to get notification attributes
getNotificationAttributes(pControlPointCharacteristic, *(uint32_t*)(pData + 4));
}
}
/**
* Develop into a BLE consumer to a distant BLE server. We're handed within the deal with of the BLE server
* because the enter parameter when the duty is created.
*/
class MyClient : public Job {
void run(void* knowledge) {
BLEAddress* pAddress = (BLEAddress*)knowledge;
BLEClient* pClient = BLEDevice::createClient();
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
BLEDevice::setSecurityCallbacks(new MySecurity());
BLESecurity* pSecurity = new BLESecurity();
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);
pSecurity->setCapability(ESP_IO_CAP_IO);
pSecurity->setRespEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
// Hook up with the distant BLE Server.
pClient->join(*pAddress);
/** BEGIN ANCS SERVICE **/
// Receive a reference to the service we're after within the distant BLE server.
BLERemoteService* pAncsService = pClient->getService(ancsServiceUUID);
if (pAncsService == nullptr) {
ESP_LOGD(LOG_TAG, "Failed to search out our service UUID: %s", ancsServiceUUID.toString().c_str());
return;
}
// Receive a reference to the traits within the service of the distant BLE server.
BLERemoteCharacteristic* pNotificationSourceCharacteristic = pAncsService->getCharacteristic(notificationSourceCharacteristicUUID);
if (pNotificationSourceCharacteristic == nullptr) {
ESP_LOGD(LOG_TAG, "Failed to search out our attribute UUID: %s", notificationSourceCharacteristicUUID.toString().c_str());
return;
}
pControlPointCharacteristic = pAncsService->getCharacteristic(controlPointCharacteristicUUID);
if (pControlPointCharacteristic == nullptr) {
ESP_LOGD(LOG_TAG, "Failed to search out our attribute UUID: %s", controlPointCharacteristicUUID.toString().c_str());
return;
}
BLERemoteCharacteristic* pDataSourceCharacteristic = pAncsService->getCharacteristic(dataSourceCharacteristicUUID);
if (pDataSourceCharacteristic == nullptr) {
ESP_LOGD(LOG_TAG, "Failed to search out our attribute UUID: %s", dataSourceCharacteristicUUID.toString().c_str());
return;
}
const uint8_t v[] = {0x1, 0x0};
pDataSourceCharacteristic->registerForNotify(dataSourceNotifyCallback);
pDataSourceCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)v, 2, true);
pNotificationSourceCharacteristic->registerForNotify(NotificationSourceNotifyCallback);
pNotificationSourceCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)v, 2, true);
/** END ANCS SERVICE **/
} // run
}; // MyClient
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t *param) {
Serial.println(" ");
Serial.println("********************");
Serial.println("**Machine related**");
Serial.println(BLEAddress(param->join.remote_bda).toString().c_str());
Serial.println("********************");
MyClient* pMyClient = new MyClient();
pMyClient->setStackSize(18000);
pMyClient->begin(new BLEAddress(param->join.remote_bda));
};
void onDisconnect(BLEServer* pServer) {
Serial.println(" ");
Serial.println("************************");
Serial.println("**Machine disconnected**");
Serial.println("************************");
}
};
class MainBLEServer: public Job {
void run(void *knowledge) ESP_BLE_ID_KEY_MASK);
//Begin promoting
pAdvertising->begin();
ESP_LOGD(LOG_TAG, "Promoting began!");
delay(portMAX_DELAY);
/**
* @transient Set the service solicitation (UUID)
* @param [in] uuid The UUID to set with the service solicitation knowledge. Dimension of UUID will likely be used.
*/
void _setServiceSolicitation(BLEAdvertisementData *a, BLEUUID uuid)
{
char cdata[2];
change(uuid.bitSize()) {
case 16: {
// [Len] [0x14] [UUID16] knowledge
cdata[0] = 3;
cdata[1] = ESP_BLE_AD_TYPE_SOL_SRV_UUID; // 0x14
String uuidString = String((char *)&uuid.getNative()->uuid.uuid16, 2);
a->addData(String(cdata[0], DEC) + String(cdata[1], DEC) + uuidString);
break;
}
case 128: {
// [Len] [0x15] [UUID128] knowledge
cdata[0] = 17;
cdata[1] = ESP_BLE_AD_TYPE_128SOL_SRV_UUID; // 0x15
String uuidString = String((char *)uuid.getNative()->uuid.uuid128, 16);
a->addData(String(cdata[0], DEC) + String(cdata[1], DEC) + uuidString);
break;
}
default:
return;
}
}
};
// New from 19:44
void getNotificationAttributes(BLERemoteCharacteristic* pControlPointCharacteristic, uint32_t notificationUID) {
// Command ID for Get Notification Attributes
const uint8_t commandID = 0;
// Attributes we wish to retrieve (Title, Message, AppIdentifier)
const uint8_t attributes[] = {1, 2, 3};
// Create the command to ship
std::vector<uint8_t> command;
command.push_back(commandID);
// Add the notification UID
command.push_back(notificationUID & 0xFF);
command.push_back((notificationUID >> 8) & 0xFF);
command.push_back((notificationUID >> 16) & 0xFF);
command.push_back((notificationUID >> 24) & 0xFF);
// Add the attributes and their max lengths (e.g., 100 bytes)
for (uint8_t attr : attributes) {
command.push_back(attr);
command.push_back(100);
command.push_back(0);
}
// Ship the command
pControlPointCharacteristic->writeValue(command.knowledge(), command.dimension(), true);
}
void SampleSecureServer(void)
{
MainBLEServer* pMainBleServer = new MainBLEServer();
pMainBleServer->setStackSize(20000);
pMainBleServer->begin();
Serial.print("");
Serial.print("BLEServer began.");
digitalWrite(LED_BUILTIN, HIGH); // flip the LED on (HIGH is the voltage degree)
}
void setup()
{
Serial.print("ANCS began.");
Serial.start(115200);
SampleSecureServer();
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
}