Hi Neil,
I decided to start putting together an ANCS library to use the ESP32 as a smart watch. Right now I'm a little stuck and was wondering if I could pick your brain.
Normally, for ANCS to work, the device must first advertise while soliciting service from the ANCS UUID.
I added the following function to BLEAdvertising so that you can include a service solicitation in the advert packet (this allows the device to show up in the settings panel of an iOS device).
void setServiceSolicitation(BLEUUID uuid);
/**
* @brief Set the service solicitation (UUID)
* @param [in] uuid The UUID to set with the service solicitation data. Size of UUID will be used.
*/
void BLEAdvertisementData::setServiceSolicitation(BLEUUID uuid)
{
char cdata[2];
switch(uuid.bitSize()) {
case 16: {
// [Len] [0x14] [UUID16] data
cdata[0] = 3;
cdata[1] = ESP_BLE_AD_TYPE_SOL_SRV_UUID; // 0x14
addData(std::string(cdata, 2) + std::string((char *)&uuid.getNative()->uuid.uuid16,2));
break;
}
case 128: {
// [Len] [0x15] [UUID128] data
cdata[0] = 17;
cdata[1] = ESP_BLE_AD_TYPE_128SOL_SRV_UUID; // 0x15
addData(std::string(cdata, 2) + std::string((char *)uuid.getNative()->uuid.uuid128,16));
break;
}
default:
return;
}
} // setServiceSolicitationData
Once you find the device, you can connect in the settings panel. I added the ability to bond in my code, which it does just fine. After bonded, the device shows as connected - perfect.
Here is where I'm stuck. After the device is bonded and connected, the ESP needs to switch out of a server role and into a client role to then subscribe to the ANCS service on the iOS device and read/write to the three characteristics exposed.
I may just be in way over my head, but I can't seem to find a way to force a connection to a white-listed device. Or if I'm already connected, to maintain that connection while I dismantle the server and spin up the client. Any ideas?
Here is the code that I have so far (gets as far as bonding/connecting to device after the advertising stage)
/**
* Create a new BLE server.
*/
#include "BLEDevice.h"
#include "BLEServer.h"
#include "BLEUtils.h"
#include "BLE2902.h"
#include <esp_log.h>
#include <string>
#include <Task.h>
#include "sdkconfig.h"
static char LOG_TAG[] = "SampleServer";
class MySecurity : public BLESecurityCallbacks {
uint32_t onPassKeyRequest(){
ESP_LOGI(LOG_TAG, "PassKeyRequest");
return 123456;
}
void onPassKeyNotify(uint32_t pass_key){
ESP_LOGI(LOG_TAG, "On passkey Notify number:%d", pass_key);
}
bool onSecurityRequest(){
ESP_LOGI(LOG_TAG, "On Security Request");
return true;
}
bool onConfirmPIN(unsigned int){
ESP_LOGI(LOG_TAG, "On Confrimed Pin Request");
return true;
}
void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
ESP_LOGI(LOG_TAG, "Starting BLE work!");
if(cmpl.success){
uint16_t length;
esp_ble_gap_get_whitelist_size(&length);
ESP_LOGD(LOG_TAG, "size: %d", length);
}
}
};
class MainBLEServer: public Task {
void run(void *data) {
ESP_LOGD(LOG_TAG, "Starting BLE work!");
esp_log_buffer_char(LOG_TAG, LOG_TAG, sizeof(LOG_TAG));
esp_log_buffer_hex(LOG_TAG, LOG_TAG, sizeof(LOG_TAG));
// Initialize device
BLEDevice::init("Watch");
BLEServer* pServer = BLEDevice::createServer();
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
BLEDevice::setSecurityCallbacks(new MySecurity());
// Advertising parameters:
// Soliciting ANCS
BLEAdvertising *pAdvertising = pServer->getAdvertising();
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
oAdvertisementData.setFlags(0x01);
oAdvertisementData.setServiceSolicitation(BLEUUID("7905F431-B5CE-4E99-A40F-4B1E122D00D0"));
pAdvertising->setAdvertisementData(oAdvertisementData);
// Set security
BLESecurity *pSecurity = new BLESecurity();
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);
pSecurity->setCapability(ESP_IO_CAP_OUT);
pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
//Start advertising
pAdvertising->start();
ESP_LOGD(LOG_TAG, "Advertising started!");
delay(portMAX_DELAY);
}
};
void SampleSecureServer(void)
{
//esp_log_level_set("*", ESP_LOG_DEBUG);
MainBLEServer* pMainBleServer = new MainBLEServer();
pMainBleServer->setStackSize(20000);
pMainBleServer->start();
} // app_main
void setup()
{
SampleSecureServer();
}
void loop()
{
delay(100);
}
Thanks a ton!
Hi,
i have question. Because bluetooth LE security is part of bluetooth v4.2, can you confirm that your iOS device is at least v4.2? If not, can you try to rewrite your code to not use security, or use only encrypted connection?
I’m working with an iPhone 8, so it should b able to handle up to 5.0. I think the 6 was the first iOS device with 4.2. I believe the security is a requirement of the ANCS protocol.
I was thinking about it a bit more during my commute home. Is there a getWhitelistedDeviceAddress call? Or a way to just force the BLEClient to a whitelisted device?
Can you provide some logs?
Here ya go!
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:956
load:0x40078000,len:0
load:0x40078000,len:13076
entry 0x40078a58
[D][ANCS_ADV_CLIENT_TEST.ino:57] run(): Starting BLE work!
[D][BLEDevice.cpp:69] createServer(): >> createServer
[D][BLEServer.cpp:304] registerApp(): >> registerApp - 0
[D][BLEDevice.cpp:95] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_REG_EVT
[D][BLEUtils.cpp:1647] dumpGattServerEvent(): GATT ServerEvent: ESP_GATTS_REG_EVT
[D][BLEUtils.cpp:1791] dumpGattServerEvent(): [status: ESP_GATT_OK, app_id: 0]
[D][BLEServer.cpp:176] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_REG_EVT
[D][BLEServer.cpp:308] registerApp(): << registerApp
[D][BLEDevice.cpp:76] createServer(): << createServer
[D][[LESBLEAr.ert:29ng.cpnd14GATsetrvvervenem): <ataand >GATetArvertvsnt
tData
[D][BLEA[verBLEinglsppp1410 se duveGapsemnt(D:taec: <ed atGAdvevensemenP_Gta
L[_AD[BLATAvertiSingCOMp:LET4]EVT
[()[BL> silst: cp:1omA] Datp: 1Eveustom [snReus: 0eDa[D] 0L
[DrveLEApp:13isihancpp:19Ev st(): ): Seno r .v. ha ading ise event[BLEAdvertising.cpp:231[ staLt()ils<cst:10
9[D]dAmCGaADVenLIENT_eceT.idoa 4APruv(n: AESertAsiBL _taCAed!
_DATA_SET_COMPLETE_EVT
[D][BLEUtils.cpp:1285] dumpGapEvent(): [status: 0]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_ADV_START_COMPLETE_EVT
[D][BLEUtils.cpp:1123] dumpGapEvent(): [status: 0]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEDevice.cpp:95] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_CONNECT_EVT
[D][BLEUtils.cpp:1647] dumpGattServerEvent(): GATT ServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLEUtils.cpp:1707] dumpGattServerEvent(): [conn_id: 0, remote_bda: AA:AA:AA:AA:AA:AA]
[D][BLEServer.cpp:176] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLEServer.cpp:294] handleGATTServerEvent(): << handleGATTServerEvent
[0;31mE (58047) BT: lmp_version_below LMP version 6 < 8[0m
[0;31mE (58316) BT: Call back not found for application conn_id=3[0m
[D][BLEDevice.cpp:95] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_MTU_EVT
[D][BLEUtils.cpp:1647] dumpGattServerEvent(): GATT ServerEvent: ESP_GATTS_MTU_EVT
[D][BLEUtils.cpp:1766] dumpGattServerEvent(): [conn_id: 0, mtu: 517]
[I][BLEDevice.cpp:110] gattServerEventHandler(): ESP_GATTS_MTU_EVT, MTU 517
[D][BLEServer.cpp:176] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_MTU_EVT
[D][BLEServer.cpp:294] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT
[D][BLEUtils.cpp:1343] dumpGapEvent(): [status: 16, bd_addr: AA:AA:AA:AA:AA:AA, min_int: 6, max_int: 6, latency: 0, conn_int: 24, timeout: 72]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[0;31mE (59996) BT: FOR LE SC LTK IS USED INSTEAD OF STK[0m
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_LENC
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_PENC
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_LID
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_PID
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_AUTH_CMPL_EVT
[D][BLEUtils.cpp:1160] dumpGapEvent(): [bd_addr: AA:AA:AA:AA:AA:AA, key_present: 0, key: ***, key_type: 0, success: 1, fail_reason: 0, addr_type: ***, dev_type: ESP_BT_DEVICE_TYPE_BLE]
[I][ANCS_ADV_CLIENT_TEST.ino:46] onAuthenticationComplete(): Starting BLE work!
[D][ANCS_ADV_CLIENT_TEST.ino:50] onAuthenticationComplete(): size: 12
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT
[D][BLEUtils.cpp:1343] dumpGapEvent(): [status: 0, bd_addr: AA:AA:AA:AA:AA:AA, min_int: 24, max_int: 24, latency: 0, conn_int: 36, timeout: 72]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
2 questions:
BT: lmp_version_below LMP version 6 < 8, do you have this message each time when you are connecting this device to esp32 or just sometimes?FOR LE SC LTK IS USED INSTEAD OF STK�[0m
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_LENC
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_PENC
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_LID
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_PID
Sorry, I should have mentioned: that last log I purposefully forced phone to forget the ESP before rebooting. I wanted to show the whole pairing process. Below is another log. In it, I did the following:
The second time I connected, I didn't exchange keys or have to acknowledge the pairing. Only the first time. As for why the phone is only showing as 4.0 I'm not sure...
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:956
load:0x40078000,len:0
load:0x40078000,len:13076
entry 0x40078a58
[D][ANCS_ADV_CLIENT_TEST.ino:57] run(): Starting BLE work!
[D][BLEDevice.cpp:69] createServer(): >> createServer
[D][BLEServer.cpp:304] registerApp(): >> registerApp - 0
[D][BLEDevice.cpp:95] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_REG_EVT
[D][BLEUtils.cpp:1647] dumpGattServerEvent(): GATT ServerEvent: ESP_GATTS_REG_EVT
[D][BLEUtils.cpp:1791] dumpGattServerEvent(): [status: ESP_GATT_OK, app_id: 0]
[D][BLEServer.cpp:176] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_REG_EVT
[D][BLEServer.cpp:308] registerApp(): << registerApp
[D][BLEDevice.cpp:76] createServer(): << createServer
[D][[D]SerEAdvcptis94g cppdle0] TStrverrtint()nt<< a()dleGAsTSedverEisetentData
[D][BLEAdvert[BLng.ils:1pp: se1] verpGsemvenD(ta R: eivsetaAGAertvente tDa_GAP_BLED]DV_EAdA_rAW_ing_COpMPLET] sVTrt(D][>> Utart: cpsto111]Daump 1,Evest():cantatpon 0D
t[: 0B
ESe[BLr.cver134ingandl:G94]venart()BLE nover vic haadvintiGAd event!B
EAdvertising.cpp:231] sta][B): <ils.artp:[D][]NCSmpGa_ELInNT): ST.enoe84a rAn ):endveEtisiAg PtarE_SCAN_RSP_DATA_SET_COMPLETE_EVT
[D][BLEUtils.cpp:1285] dumpGapEvent(): [status: 0]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_ADV_START_COMPLETE_EVT
[D][BLEUtils.cpp:1123] dumpGapEvent(): [status: 0]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEDevice.cpp:95] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_CONNECT_EVT
[D][BLEUtils.cpp:1647] dumpGattServerEvent(): GATT ServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLEUtils.cpp:1707] dumpGattServerEvent(): [conn_id: 0, remote_bda: AA:AA:AA:AA:AA:AA]
[D][BLEServer.cpp:176] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLEServer.cpp:294] handleGATTServerEvent(): << handleGATTServerEvent
[0;31mE (9791) BT: lmp_version_below LMP version 6 < 8[0m
[0;31mE (10179) BT: Call back not found for application conn_id=3[0m
[D][BLEDevice.cpp:95] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_MTU_EVT
[D][BLEUtils.cpp:1647] dumpGattServerEvent(): GATT ServerEvent: ESP_GATTS_MTU_EVT
[D][BLEUtils.cpp:1766] dumpGattServerEvent(): [conn_id: 0, mtu: 517]
[I][BLEDevice.cpp:110] gattServerEventHandler(): ESP_GATTS_MTU_EVT, MTU 517
[D][BLEServer.cpp:176] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_MTU_EVT
[D][BLEServer.cpp:294] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT
[D][BLEUtils.cpp:1343] dumpGapEvent(): [status: 16, bd_addr: AA:AA:AA:AA:AA:AA, min_int: 6, max_int: 6, latency: 0, conn_int: 24, timeout: 72]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[0;31mE (12699) BT: FOR LE SC LTK IS USED INSTEAD OF STK[0m
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_LENC
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_PENC
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_LID
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_KEY_EVT
[D][BLEUtils.cpp:1358] dumpGapEvent(): *** dumpGapEvent: Logger not coded ***
[I][BLEDevice.cpp:231] gapEventHandler(): key type = ESP_LE_KEY_PID
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_AUTH_CMPL_EVT
[D][BLEUtils.cpp:1160] dumpGapEvent(): [bd_addr: AA:AA:AA:AA:AA:AA, key_present: 0, key: ***, key_type: 0, success: 1, fail_reason: 0, addr_type: ***, dev_type: ESP_BT_DEVICE_TYPE_BLE]
[I][ANCS_ADV_CLIENT_TEST.ino:46] onAuthenticationComplete(): Starting BLE work!
[D][ANCS_ADV_CLIENT_TEST.ino:50] onAuthenticationComplete(): size: 12
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT
[D][BLEUtils.cpp:1343] dumpGapEvent(): [status: 0, bd_addr: AA:AA:AA:AA:AA:AA, min_int: 24, max_int: 24, latency: 0, conn_int: 36, timeout: 72]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[0;31mE (19996) BT: bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0013[0m
[D][BLEDevice.cpp:95] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_DISCONNECT_EVT
[D][BLEUtils.cpp:1647] dumpGattServerEvent(): GATT ServerEvent: ESP_GATTS_DISCONNECT_EVT
[D][BLEUtils.cpp:1723] dumpGattServerEvent(): [conn_id: 0, remote_bda: AA:AA:AA:AA:AA:AA]
[D][BLEServer.cpp:176] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_DISCONNECT_EVT
[D][BLEServer.cpp:333] startAdvertising(): >> startAdvertising
[D][BLEAdvertising.cpp:174] start(): >> start: customAdvData: 1, customScanResponseData: 0
[D][BLEAdvertising.cpp:194] start(): - no services advertised
[D][BLEAdvertising.cpp:231] start(): << start
[D][BLEServer.cpp:335] startAdvertising(): << startAdvertising
[D][BLEServer.cpp:294] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT
[D][BLEUtils.cpp:1285] dumpGapEvent(): [status: 0]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_ADV_START_COMPLETE_EVT
[D][BLEUtils.cpp:1123] dumpGapEvent(): [status: 0]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEDevice.cpp:95] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_CONNECT_EVT
[D][BLEUtils.cpp:1647] dumpGattServerEvent(): GATT ServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLEUtils.cpp:1707] dumpGattServerEvent(): [conn_id: 0, remote_bda: AA:AA:AA:AA:AA:AA]
[D][BLEServer.cpp:176] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLEServer.cpp:294] handleGATTServerEvent(): << handleGATTServerEvent
[0;31mE (25958) BT: lmp_version_below LMP version 6 < 8[0m
[0;31mE (26137) BT: l2cble_start_conn_update, the last connection update command still pending.[0m
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_AUTH_CMPL_EVT
[D][BLEUtils.cpp:1160] dumpGapEvent(): [bd_addr: AA:AA:AA:AA:AA:AA, key_present: 0, key: ***, key_type: 0, success: 1, fail_reason: 0, addr_type: ***, dev_type: ESP_BT_DEVICE_TYPE_BLE]
[I][ANCS_ADV_CLIENT_TEST.ino:46] onAuthenticationComplete(): Starting BLE work!
[D][ANCS_ADV_CLIENT_TEST.ino:50] onAuthenticationComplete(): size: 12
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT
[D][BLEUtils.cpp:1343] dumpGapEvent(): [status: 0, bd_addr: AA:AA:AA:AA:AA:AA, min_int: 6, max_int: 6, latency: 0, conn_int: 24, timeout: 600]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
[0;31mE (26686) BT: Call back not found for application conn_id=3[0m
[D][BLEDevice.cpp:95] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_MTU_EVT
[D][BLEUtils.cpp:1647] dumpGattServerEvent(): GATT ServerEvent: ESP_GATTS_MTU_EVT
[D][BLEUtils.cpp:1766] dumpGattServerEvent(): [conn_id: 0, mtu: 517]
[I][BLEDevice.cpp:110] gattServerEventHandler(): ESP_GATTS_MTU_EVT, MTU 517
[D][BLEServer.cpp:176] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_MTU_EVT
[D][BLEServer.cpp:294] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEUtils.cpp:1091] dumpGapEvent(): Received a GAP event: ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT
[D][BLEUtils.cpp:1343] dumpGapEvent(): [status: 0, bd_addr: AA:AA:AA:AA:AA:AA, min_int: 24, max_int: 24, latency: 0, conn_int: 36, timeout: 72]
[D][BLEServer.cpp:134] handleGAPEvent(): BLEServer ... handling GAP event!
No problem. Looks like device is connected with esp32, which means bonding works good.
Now you can try in server callback in onConnect try to create BLEClient and connect to iOS device.
Oh, interesting. I will try that in the morning! Thanks, will report back
Hey @chegewara or @nkolban , any chance you can point me in the right direction to find the remote device address that connected to a server? I think I know where I need to go next, but I can't seem to find how to spin up a client connected to an address I'm already connected to.
Basically, what I'm looking for is something like:
"advertisedDevice.getAddress().toString().c_str()"
So I can then take that and pass that to the client for connection.
Thanks!
If it can be printed out here, then it can be retrieved somewhere:
[D][BLEUtils.cpp:1707] dumpGattServerEvent(): [conn_id: 0, remote_bda: AA:AA:AA:AA:AA:AA]
That was my exact thought. But as I was digging through the dumpGattServerEvent(), I couldn't seem to find where the param was sent to it from.
I see this line, where the connect.remote_bda is exactly what I want. I have no idea where param is being passed to it though.
esp_ble_set_encryption(param->connect.remote_bda, BLEDevice::m_securityLevel);
Its passed from low level bluedroid stack as events parameter. Now, as you've found where it can be retrieved from, you can add variable to this class and you will be able to get it when you need it. Its not much work, 2 to 5 lines of code.
I'm sorry if this is a bit of a silly question, I'm just rather new to this. Would I just be adding it to the BLEDevice class?
Something like:
esp_bd_addr_t m_remoteBda;
And then in the BLEDevice::gattServerEventHandler in the ESP_GATTS_CONNECT_EVT case, add something like
BLEDevice::m_remoteBda=param->connect.remote_bda
Then in the future I can just call BLEDevice::m_remoteBda to put the address where I need it?
Yes, it sounds good.
So after adding the above, if I call:
Serial.println(BLEDevice::remoteBda.toString().c_str());
I get this error:
error: 'remoteBda' is not a member of 'BLEDevice'
Any ideas?
Check if this static esp_bd_addr_t m_remoteBda; is private or public. Needs to be public static.
In BLEDevice.h
/**
* @brief %BLE functions.
*/
class BLEDevice {
public:
static BLEClient* createClient(); // Create a new BLE client.
static BLEServer* createServer(); // Cretae a new BLE server.
static BLEAddress getAddress(); // Retrieve our own local BD address.
static BLEScan* getScan(); // Get the scan object
static std::string getValue(BLEAddress bdAddress, BLEUUID serviceUUID, BLEUUID characteristicUUID); // Get the value of a characteristic of a service on a server.
static void init(std::string deviceName); // Initialize the local BLE environment.
static void setPower(esp_power_level_t powerLevel); // Set our power level.
static void setValue(BLEAddress bdAddress, BLEUUID serviceUUID, BLEUUID characteristicUUID, std::string value); // Set the value of a characteristic on a service on a server.
static std::string toString(); // Return a string representation of our device.
static void whiteListAdd(BLEAddress address); // Add an entry to the BLE white list.
static void whiteListRemove(BLEAddress address); // Remove an entry from the BLE white list.
static void setEncryptionLevel(esp_ble_sec_act_t level);
static void setSecurityCallbacks(BLESecurityCallbacks* pCallbacks);
static esp_err_t setMTU(uint16_t mtu);
static uint16_t getMTU();
static esp_bd_addr_t m_remoteBda;
Then in BLEDevice.cpp
/**
* Singletons for the BLEDevice.
*/
BLEServer* BLEDevice::m_pServer = nullptr;
BLEScan* BLEDevice::m_pScan = nullptr;
BLEClient* BLEDevice::m_pClient = nullptr;
bool initialized = false; // Have we been initialized?
esp_ble_sec_act_t BLEDevice::m_securityLevel = (esp_ble_sec_act_t)0;
BLESecurityCallbacks* BLEDevice::m_securityCallbacks = nullptr;
uint16_t BLEDevice::m_localMTU = 23;
esp_bd_addr_t BLEDevice::m_remoteBda;
And
/**
* @brief Handle GATT server events.
*
* @param [in] event The event that has been newly received.
* @param [in] gatts_if The connection to the GATT interface.
* @param [in] param Parameters for the event.
*/
/* STATIC */ void BLEDevice::gattServerEventHandler(
esp_gatts_cb_event_t event,
esp_gatt_if_t gatts_if,
esp_ble_gatts_cb_param_t* param
) {
ESP_LOGD(LOG_TAG, "gattServerEventHandler [esp_gatt_if: %d] ... %s",
gatts_if,
BLEUtils::gattServerEventTypeToString(event).c_str());
BLEUtils::dumpGattServerEvent(event, gatts_if, param);
switch(event) {
case ESP_GATTS_CONNECT_EVT: {
BLEDevice::m_localMTU = 23;
if(BLEDevice::m_securityLevel){
BLEDevice::m_remoteBda=param->connect.remote_bda;
esp_ble_set_encryption(param->connect.remote_bda, BLEDevice::m_securityLevel);
}
break;
} // ESP_GATTS_CONNECT_EVT
And I'm still getting the error:
error: 'remoteBda' is not a member of 'BLEDevice'
Serial.println(BLEDevice::remoteBda.toString().c_str());
Try to initialize it here:
/**
* Singletons for the BLEDevice.
*/
BLEServer* BLEDevice::m_pServer = nullptr;
BLEScan* BLEDevice::m_pScan = nullptr;
BLEClient* BLEDevice::m_pClient = nullptr;
bool initialized = false; // Have we been initialized?
esp_ble_sec_act_t BLEDevice::m_securityLevel = (esp_ble_sec_act_t)0;
BLESecurityCallbacks* BLEDevice::m_securityCallbacks = nullptr;
uint16_t BLEDevice::m_localMTU = 23;
esp_bd_addr_t BLEDevice::m_remoteBda = {00,00,00,00,00,00}; <-- HERE, but im not sure
New and exciting error!
error: invalid array assignment
BLEDevice::m_remoteBda=param->connect.remote_bda;
This is definition, you need to initialize it:
http://esp-idf.readthedocs.io/en/latest/api-reference/bluetooth/esp_bt_defs.html#_CPPv213esp_bd_addr_t
Im not good at C and C++, sorry.
Got it!
/**
* Singletons for the BLEDevice.
*/
BLEServer* BLEDevice::m_pServer = nullptr;
BLEScan* BLEDevice::m_pScan = nullptr;
BLEClient* BLEDevice::m_pClient = nullptr;
bool initialized = false; // Have we been initialized?
esp_ble_sec_act_t BLEDevice::m_securityLevel = (esp_ble_sec_act_t)0;
BLESecurityCallbacks* BLEDevice::m_securityCallbacks = nullptr;
uint16_t BLEDevice::m_localMTU = 23;
esp_bd_addr_t BLEDevice::m_remoteBda;
And here is the important part! Have to use memcpy to copy the array.
/**
* @brief Handle GATT server events.
*
* @param [in] event The event that has been newly received.
* @param [in] gatts_if The connection to the GATT interface.
* @param [in] param Parameters for the event.
*/
/* STATIC */ void BLEDevice::gattServerEventHandler(
esp_gatts_cb_event_t event,
esp_gatt_if_t gatts_if,
esp_ble_gatts_cb_param_t* param
) {
ESP_LOGD(LOG_TAG, "gattServerEventHandler [esp_gatt_if: %d] ... %s",
gatts_if,
BLEUtils::gattServerEventTypeToString(event).c_str());
BLEUtils::dumpGattServerEvent(event, gatts_if, param);
switch(event) {
case ESP_GATTS_CONNECT_EVT: {
BLEDevice::m_localMTU = 23;
if(BLEDevice::m_securityLevel){
memcpy(m_remoteBda, (param->connect.remote_bda), sizeof(param->connect.remote_bda));
esp_ble_set_encryption(param->connect.remote_bda, BLEDevice::m_securityLevel);
}
break;
} // ESP_GATTS_CONNECT_EVT
Back to work on the rest of the library, will continue to update as I make progress.

Wooo! Client is connecting and found the characteristics on phone!
Next step is to ID those notifications and make use of them!
If anyone is looking for an ANCS library in the future, here is a fully functional ANCS example.
I apologize the code is not the cleanest, but it works! I get all notifications from my phone streaming onto the UART lines. I will clean things up later and create a pull request.
/**
* Create a new BLE server.
*/
#include "BLEDevice.h"
#include "BLEServer.h"
#include "BLEClient.h"
#include "BLEUtils.h"
#include "BLE2902.h"
#include <esp_log.h>
#include <string>
#include <Task.h>
#include "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");
class MySecurity : public BLESecurityCallbacks {
uint32_t onPassKeyRequest(){
ESP_LOGI(LOG_TAG, "PassKeyRequest");
return 123456;
}
void onPassKeyNotify(uint32_t pass_key){
ESP_LOGI(LOG_TAG, "On passkey Notify number:%d", pass_key);
}
bool onSecurityRequest(){
ESP_LOGI(LOG_TAG, "On Security Request");
return true;
}
bool onConfirmPIN(unsigned int){
ESP_LOGI(LOG_TAG, "On Confrimed Pin Request");
return true;
}
void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
ESP_LOGI(LOG_TAG, "Starting BLE work!");
if(cmpl.success){
uint16_t length;
esp_ble_gap_get_whitelist_size(&length);
ESP_LOGD(LOG_TAG, "size: %d", length);
}
}
};
static void dataSourceNotifyCallback(
BLERemoteCharacteristic* pDataSourceCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
Serial.print("Notify callback for characteristic ");
Serial.print(pDataSourceCharacteristic->getUUID().toString().c_str());
Serial.print(" of data length ");
Serial.println(length);
}
static void NotificationSourceNotifyCallback(
BLERemoteCharacteristic* pNotificationSourceCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
// Serial.print("Notify callback for characteristic ");
// Serial.println(pNotificationSourceCharacteristic->getUUID().toString().c_str());
// Serial.print("Data: ");
// for(int i=0; i<length; i++)
// {
// Serial.print(String(pData[i]));
// }
if(pData[0]==0)
{
Serial.println("New notification!");
switch(pData[2])
{
case 0:
Serial.println("Category: Other");
break;
case 1:
Serial.println("Category: Incoming call");
break;
case 2:
Serial.println("Category: Missed call");
break;
case 3:
Serial.println("Category: Voicemail");
break;
case 4:
Serial.println("Category: Social");
break;
case 5:
Serial.println("Category: Schedule");
break;
case 6:
Serial.println("Category: Email");
break;
case 7:
Serial.println("Category: News");
break;
case 8:
Serial.println("Category: Health");
break;
case 9:
Serial.println("Category: Business");
break;
case 10:
Serial.println("Category: Location");
break;
case 11:
Serial.println("Category: Entertainment");
break;
default:
break;
}
}
}
/**
* Become a BLE client to a remote BLE server. We are passed in the address of the BLE server
* as the input parameter when the task is created.
*/
class MyClient: public Task {
void run(void* data) {
BLEAddress* pAddress = (BLEAddress*)data;
BLEClient* pClient = BLEDevice::createClient();
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
BLEDevice::setSecurityCallbacks(new MySecurity());
BLESecurity *pSecurity = new BLESecurity();
//pSecurity->setKeySize();
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);
// Connect to the remove BLE Server.
pClient->connect(*pAddress);
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(ancsServiceUUID);
if (pRemoteService == nullptr) {
ESP_LOGD(LOG_TAG, "Failed to find our service UUID: %s", ancsServiceUUID.toString().c_str());
return;
}
// Obtain a reference to the characteristic in the service of the remote BLE server.
BLERemoteCharacteristic* pNotificationSourceCharacteristic = pRemoteService->getCharacteristic(notificationSourceCharacteristicUUID);
if (pNotificationSourceCharacteristic == nullptr) {
ESP_LOGD(LOG_TAG, "Failed to find our characteristic UUID: %s", notificationSourceCharacteristicUUID.toString().c_str());
return;
}
// Obtain a reference to the characteristic in the service of the remote BLE server.
BLERemoteCharacteristic* pControlPointCharacteristic = pRemoteService->getCharacteristic(controlPointCharacteristicUUID);
if (pControlPointCharacteristic == nullptr) {
ESP_LOGD(LOG_TAG, "Failed to find our characteristic UUID: %s", controlPointCharacteristicUUID.toString().c_str());
return;
}
// Obtain a reference to the characteristic in the service of the remote BLE server.
BLERemoteCharacteristic* pDataSourceCharacteristic = pRemoteService->getCharacteristic(dataSourceCharacteristicUUID);
if (pDataSourceCharacteristic == nullptr) {
ESP_LOGD(LOG_TAG, "Failed to find our characteristic 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);
} // run
}; // MyClient
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
Serial.println("********************");
Serial.println("**Device connected**");
Serial.println(BLEAddress(BLEDevice::m_remoteBda).toString().c_str());
Serial.println("********************");
MyClient* pMyClient = new MyClient();
pMyClient->setStackSize(18000);
pMyClient->start(new BLEAddress(BLEDevice::m_remoteBda));
};
void onDisconnect(BLEServer* pServer) {
Serial.println("************************");
Serial.println("**Device disconnected**");
Serial.println("************************");
}
};
class MainBLEServer: public Task {
void run(void *data) {
ESP_LOGD(LOG_TAG, "Starting BLE work!");
esp_log_buffer_char(LOG_TAG, LOG_TAG, sizeof(LOG_TAG));
esp_log_buffer_hex(LOG_TAG, LOG_TAG, sizeof(LOG_TAG));
// Initialize device
BLEDevice::init("Watch");
BLEServer* pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
BLEDevice::setSecurityCallbacks(new MySecurity());
// Advertising parameters:
// Soliciting ANCS
BLEAdvertising *pAdvertising = pServer->getAdvertising();
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
oAdvertisementData.setFlags(0x01);
oAdvertisementData.setServiceSolicitation(BLEUUID("7905F431-B5CE-4E99-A40F-4B1E122D00D0"));
pAdvertising->setAdvertisementData(oAdvertisementData);
// Set security
BLESecurity *pSecurity = new BLESecurity();
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);
pSecurity->setCapability(ESP_IO_CAP_OUT);
pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
//Start advertising
pAdvertising->start();
ESP_LOGD(LOG_TAG, "Advertising started!");
delay(portMAX_DELAY);
}
};
void SampleSecureServer(void)
{
//esp_log_level_set("*", ESP_LOG_DEBUG);
MainBLEServer* pMainBleServer = new MainBLEServer();
pMainBleServer->setStackSize(20000);
pMainBleServer->start();
} // app_main
void setup()
{
Serial.begin(115200);
SampleSecureServer();
}
void loop()
{
delay(100);
}
Nice work. You can create new project on github with this project, its your project, and then you can share with community on forum.
I plan on it. I have a few more goodies up my sleeve that will come along with it. For now, I figured I'd leave this here in case anyone else needs it while I get the rest of the project ready :)
@S-March What IOS do you have on iPhone 8?
I’m running on 11.2.6
@S-March
I am using Arduino 1.8.5 and tried to compile your ANCS example with the result that i get such errors:
ESP32_ANCS:129: error: expected class-name before '{' token
class MyClient: public Task {
^
/Users/bitwerk/Documents/Arduino ESP32/ESP32_ANCS/ESP32_ANCS.ino: In member function 'virtual void MyServerCallbacks::onConnect(BLEServer)':
ESP32_ANCS:185: error: 'm_remoteBda' is not a member of 'BLEDevice'
Serial.println(BLEAddress(BLEDevice::m_remoteBda).toString().c_str());
^
ESP32_ANCS:188: error: 'class MyClient' has no member named 'setStackSize'
pMyClient->setStackSize(18000);
^
ESP32_ANCS:189: error: 'class MyClient' has no member named 'start'
pMyClient->start(new BLEAddress(BLEDevice::m_remoteBda));
^
ESP32_ANCS:189: error: 'm_remoteBda' is not a member of 'BLEDevice'
pMyClient->start(new BLEAddress(BLEDevice::m_remoteBda));
^
/Users/bitwerk/Documents/Arduino ESP32/ESP32_ANCS/ESP32_ANCS.ino: At global scope:
ESP32_ANCS:199: error: expected class-name before '{' token
class MainBLEServer: public Task {
^
/Users/bitwerk/Documents/Arduino ESP32/ESP32_ANCS/ESP32_ANCS.ino: In member function 'void MainBLEServer::run(void)':
ESP32_ANCS:217: error: 'class BLEAdvertisementData' has no member named 'setServiceSolicitation'
oAdvertisementData.setServiceSolicitation(BLEUUID("7905F431-B5CE-4E99-A40F-4B1E122D00D0"));
^
/Users/bitwerk/Documents/Arduino ESP32/ESP32_ANCS/ESP32_ANCS.ino: In function 'void SampleSecureServer()':
ESP32_ANCS:239: error: 'class MainBLEServer' has no member named 'setStackSize'
pMainBleServer->setStackSize(20000);
^
ESP32_ANCS:240: error: 'class MainBLEServer' has no member named 'start'
pMainBleServer->start();
^
What am i doing wrong?
@krewtib make sure you read through the previous comments. I had to add m_remoteBda to BLEDevice.h If you scroll up a bit you will see where I added it.
There is no Task class in arduino library. You can try to copy it, but i dont remember if it works in arduino environment.
This is what I used:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/Task.h
Wow. Thanks for so much help.
After making all the changes there is still one error left:
/var/folders/xj/nnxznz2d4c1bvst5v_mjq3yr0000gn/T/arduino_modified_sketch_654806/ESP32_ANCS.ino: In member function 'virtual void MainBLEServer::run(void*)':
ESP32_ANCS:217: error: 'class BLEAdvertisementData' has no member named 'setServiceSolicitation'
oAdvertisementData.setServiceSolicitation(BLEUUID("7905F431-B5CE-4E99-A40F-4B1E122D00D0"));
^
'class BLEAdvertisementData' has no member named 'setServiceSolicitation'
Am 16.05.2018 um 22:56 schrieb S-March notifications@github.com:
This is what I used:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/Task.h https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/Task.h
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-389662765, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wpFKjA9q-QttbmtcDlMjr8wWkz_Hks5tzJJ1gaJpZM4SlAVo.
Take a look at the very first post in this thread, I created a setServiceSolicitation() in BLEAdvertising.h
first i added in BLEAdvertising.h:
in class BLEAdvertisementData {
in public:
behind
void setShortName(std::string name);
void setServiceSolicitation(BLEUUID uuid);
then i added in BLESdvertising.cpp
behind
std::string BLEAdvertisementData::getPayload() {
return m_payload;
} // getPayload
the routine from your post
/**
but still i get a error:
ESP32_ANCS:217: error: 'class BLEAdvertisementData' has no member named 'setServiceSolicitation'
Am 16.05.2018 um 23:25 schrieb S-March notifications@github.com:
Take a look at the very first post in this thread, I created a setServiceSolicitation() in BLEAdvertising.h
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-389670889, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wuqT_XgfV-RHWeco-NqphDhpwBCzks5tzJlTgaJpZM4SlAVo.
Hmm... In my BLEAdvertising.cpp I put the following section of code immediately after the following function.
void BLEAdvertisementData::setPartialServices(BLEUUID uuid)
/**
* @brief Set the service solicitation (UUID)
* @param [in] uuid The UUID to set with the service solicitation data. Size of UUID will be used.
*/
void BLEAdvertisementData::setServiceSolicitation(BLEUUID uuid)
{
char cdata[2];
switch(uuid.bitSize()) {
case 16: {
// [Len] [0x14] [UUID16] data
cdata[0] = 3;
cdata[1] = ESP_BLE_AD_TYPE_SOL_SRV_UUID; // 0x14
addData(std::string(cdata, 2) + std::string((char *)&uuid.getNative()->uuid.uuid16,2));
break;
}
case 128: {
// [Len] [0x15] [UUID128] data
cdata[0] = 17;
cdata[1] = ESP_BLE_AD_TYPE_128SOL_SRV_UUID; // 0x15
addData(std::string(cdata, 2) + std::string((char *)uuid.getNative()->uuid.uuid128,16));
break;
}
default:
return;
}
} // setServiceSolicitationData
and my .h file looks like this:
/*
* BLEAdvertising.h
*
* Created on: Jun 21, 2017
* Author: kolban
*/
#ifndef COMPONENTS_CPP_UTILS_BLEADVERTISING_H_
#define COMPONENTS_CPP_UTILS_BLEADVERTISING_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <esp_gap_ble_api.h>
#include "BLEUUID.h"
#include <vector>
/**
* @brief Advertisement data set by the programmer to be published by the %BLE server.
*/
class BLEAdvertisementData {
// Only a subset of the possible BLE architected advertisement fields are currently exposed. Others will
// be exposed on demand/request or as time permits.
//
public:
void setAppearance(uint16_t appearance);
void setCompleteServices(BLEUUID uuid);
void setFlags(uint8_t);
void setManufacturerData(std::string data);
void setName(std::string name);
void setPartialServices(BLEUUID uuid);
void setServiceData(BLEUUID uuid, std::string data);
void setServiceSolicitation(BLEUUID uuid);
void setShortName(std::string name);
private:
friend class BLEAdvertising;
std::string m_payload; // The payload of the advertisement.
void addData(std::string data); // Add data to the payload.
std::string getPayload(); // Retrieve the current advert payload.
}; // BLEAdvertisementData
/**
* @brief Perform and manage %BLE advertising.
*
* A %BLE server will want to perform advertising in order to make itself known to %BLE clients.
*/
class BLEAdvertising {
public:
BLEAdvertising();
void addServiceUUID(BLEUUID serviceUUID);
void addServiceUUID(const char* serviceUUID);
void start();
void stop();
void setAppearance(uint16_t appearance);
void setMaxInterval(uint16_t maxinterval);
void setMinInterval(uint16_t mininterval);
void setAdvertisementData(BLEAdvertisementData& advertisementData);
void setScanFilter(bool scanRequertWhitelistOnly, bool connectWhitelistOnly);
void setScanResponseData(BLEAdvertisementData& advertisementData);
private:
esp_ble_adv_data_t m_advData;
esp_ble_adv_params_t m_advParams;
std::vector<BLEUUID> m_serviceUUIDs;
bool m_customAdvData; // Are we using custom advertising data?
bool m_customScanResponseData; // Are we using custom scan response data?
};
#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BLEADVERTISING_H_ */
Had a Typo in my Source. Now everything compiles and can be downloaded and the Device „Watch“ can be connected via Bluetooth.
I sent some mails to my iPhone But i don’t see any reactions of Notifications and after some time the Device disconnects.
My Output:
Device connected
6b:a0:79:4c:ae:73
.[0;31mE (244791) BT: lmp_version_below LMP version 6 < 8.[0m
.[0;31mE (244792) BT: earlier enc was not done for same device
.[0m
.[0;31mE (244797) BT: btc_gattc_call_handler().[0m
.[0;31mE (244802) BT: application already registered..[0m
.[0;31mE (244807) BT: Register with GATT stack failed.
.[0m
.[0;31mE (244812) BT: application already registered..[0m
.[0;31mE (244817) BT: Register with GATT stack failed.
.[0m
.[0;31mE (244824) BT: bta_gattc_process_api_open Failed, unknown client_if: 0.[0m
.[0;31mE (244938) BT: l2cble_start_conn_update, the last connection update command still pending..[0m
.[0;31mE (245208) BT: Call back not found for application conn_id=3.[0m
.[0;31mE (245209) BT: Call back not found for application conn_id=5.[0m
and after sometime:
Device disconnected
Am 17.05.2018 um 00:08 schrieb S-March notifications@github.com:
Hmm... In my BLEAdvertising.cpp I put the following section of code immediately after the following function.
void BLEAdvertisementData::setPartialServices(BLEUUID uuid)/**
- @brief Set the service solicitation (UUID)
- @param [in] uuid The UUID to set with the service solicitation data. Size of UUID will be used.
*/
void BLEAdvertisementData::setServiceSolicitation(BLEUUID uuid)
{
char cdata[2];
switch(uuid.bitSize()) {
case 16: {
// [Len] [0x14] [UUID16] data
cdata[0] = 3;
cdata[1] = ESP_BLE_AD_TYPE_SOL_SRV_UUID; // 0x14
addData(std::string(cdata, 2) + std::string((char *)&uuid.getNative()->uuid.uuid16,2));
break;
}case 128: { // [Len] [0x15] [UUID128] data cdata[0] = 17; cdata[1] = ESP_BLE_AD_TYPE_128SOL_SRV_UUID; // 0x15 addData(std::string(cdata, 2) + std::string((char *)uuid.getNative()->uuid.uuid128,16)); break; } default: return;}
} // setServiceSolicitationData
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-389681552, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wltiZqnD2DhnWQiSNeF3Gb1cW1wxks5tzKNtgaJpZM4SlAVo.
On your phone, forget the device and try repairing it. If it is pairing, it should just work with code as is. What version of iOS are you running? Also when you send an email or text or something to phone, make sure you aren't accidentally reading it or removing it from the notification center. If your phone thinks you saw the notification, it won't forward them to the ESP
I am using iPhone X with IOS 11.3.1.
Did as you suggested.
Forgot the Device (The Device disconnected properly)
Paired again. I did not see any pairing data from onPassKeyRequest. But Device connected.
Sent email to phone.
Did not read the mail on the phone.
Still no respond.
Am 17.05.2018 um 17:50 schrieb S-March notifications@github.com:
On your phone, forget the device and try repairing it. If it is pairing, it should just work with code as is. What version of iOS are you running? Also when you send an email or text or something to phone, make sure you aren't accidentally reading it or removing it from the notification center. If your phone thinks you saw the notification, it won't forward them to the ESP
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-389915118, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wgCAeAwMPImoNyTF4JscO2mHliaWks5tzZxDgaJpZM4SlAVo.
Hmmm... When you paired the device what was the output on the UART stream?
You can also try turning on verbose debugging and seeing what the output is as the connection is taking place.
This is my output after start:
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun 8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:956
load:0x40078000,len:0
load:0x40078000,len:13076
entry 0x40078a58
this after pairing
Device connected
6c:c1:60:95:0d:53
[0;31mE (32000) BT: lmp_version_below LMP version 6 < 8[0m
[0;31mE (32002) BT: btc_gattc_call_handler()[0m
[0;31mE (32005) BT: l2cble_start_conn_update, the last connection update command still pending.[0m
[0;31mE (32014) BT: earlier enc was not done for same device
[0m
[0;31mE (32387) BT: Call back not found for application conn_id=3[0m
[0;31mE (32387) BT: Call back not found for application conn_id=5[0m
[0;31mE (34066) BT: bta_gattc_cmpl_cback unknown conn_id = 3, ignore data[0m
this after disconnecting
Device disconnected
[0;31mE (65057) BT: Device not found
[0m
[0;31mE (65058) BT: bta_gattc_mark_bg_conn unable to find the bg connection mask for: 6c:c1:60:95:0d:53[0m
Am 18.05.2018 um 15:57 schrieb S-March notifications@github.com:
Hmmm... When you paired the device what was the output on the UART stream?
You can also try turning on verbose debugging and seeing what the output is as the connection is taking place.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-390215611, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wiOxCsVEQfie_aC_1_GV8_eyRiBpks5tztNPgaJpZM4SlAVo.
Great work with the ANCS implementation! I am also trying to run this in the Arduino environment. But even after applying the changes mentioned here, I get tons of errors.
For example: 'class MainBLEServer' has no member named 'start'
and 'class MyClient' has no member named 'setStackSize'
I know that you are not finished with your project yet, but would one of you mind putting the working code and modified library files somewhere on github?
OK, I got to the same point as krewtib now. The behavior is the same, no notifications are displayed and it disconnects after a few seconds.
********************
**Device connected**
00:00:00:00:00:00
********************
E (29473) BT: lmp_version_below LMP version 6 < 8
E (29477) BT: earlier enc was not done for same device
E (29561) BT: resolving list can not be edited, EnQ now
E (29621) BT: Call back not found for application conn_id=3
E (29621) BT: Call back not found for application conn_id=5
E (30978) BT: FOR LE SC LTK IS USED INSTEAD OF STK
E (59478) BT: bta_gattc_conn_cback() - cif=3 connected=0 conn_id=259 reason=0x0100
E (59479) BT: p_conn is NULL in bta_gattc_conn_cback
E (59480) BT: bta_gattc_conn_cback() - cif=5 connected=0 conn_id=261 reason=0x0100
E (59487) BT: p_conn is NULL in bta_gattc_conn_cback
************************
**Device disconnected**
************************
What did the output looks like with your working solution, @S-March?
Maybe it is just a problem with Arduino.
@Max K
Maybe also a difference in the ESP32 module? Mine has following print on the lid:
ESP-WROOM-32
211-161007
FCC ID:2AC7Z—ESPWRoom32
I have got 2 of these but none of them work with this sketch.
Other sketches are running fine.
Am 22.05.2018 um 15:33 schrieb Max K notifications@github.com:
OK, I got to the same point as @krewtib https://github.com/krewtib now. The behavior is the same, no notifications are displayed and it disconnects after a few seconds.
Device connected
00:00:00:00:00:00
E (29473) BT: lmp_version_below LMP version 6 < 8
E (29477) BT: earlier enc was not done for same deviceE (29561) BT: resolving list can not be edited, EnQ now
E (29621) BT: Call back not found for application conn_id=3
E (29621) BT: Call back not found for application conn_id=5
E (30978) BT: FOR LE SC LTK IS USED INSTEAD OF STK
E (59478) BT: bta_gattc_conn_cback() - cif=3 connected=0 conn_id=259 reason=0x0100
E (59479) BT: p_conn is NULL in bta_gattc_conn_cbackE (59480) BT: bta_gattc_conn_cback() - cif=5 connected=0 conn_id=261 reason=0x0100
E (59487) BT: p_conn is NULL in bta_gattc_conn_cback
Device disconnected
What did the output looks like with your working solution, @S-March https://github.com/S-March?
Maybe it is just a problem with Arduino.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-390991507, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wj5QXDNPXB9yQT4I0qELrP7MFl_Oks5t1BOogaJpZM4SlAVo.
My board has the identical print on it. Same ID. But I doubt that this problem is hardware related. There is so much that could be configured incorrectly just because we are using the files from the Arduino library.
It would be nice if @S-March could share his code as he promissed.
Okay.
Could have been a source of errors. Let us wait for the code.
Am 22.05.2018 um 19:36 schrieb chegewara notifications@github.com:
It would be nice if @S-March https://github.com/S-March could share his code as he promissed.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-391077090, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03whKqqkJCan2YLw_cdLpqCRJ4r6XAks5t1EyYgaJpZM4SlAVo.
I don't have my full project (more than just ANCS) done yet, but I pulled out the ANCS portion of it. This code works for me on an esp32 module. I uploaded it to a module just now to verify and it is working.
https://github.com/S-March/esp32_ANCS
Let me know if you guys run into any issues.
I might be doing something wrong but I put the files from your library folder into the ESP32_BLE_Arduino library directory. Now there is this error:
C:\Users\Max\Documents\Arduino\libraries\ESP32_BLE_Arduino\src\BLEClient.cpp: In member function 'bool BLEClient::connect(BLEAddress)':
C:\Users\Max\Documents\Arduino\libraries\ESP32_BLE_Arduino\src\BLEClient.cpp:114:2: error: invalid conversion from 'int' to 'esp_ble_addr_type_t' [-fpermissive]
);
^
C:\Users\Max\Documents\Arduino\libraries\ESP32_BLE_Arduino\src\BLEClient.cpp:114:2: error: too few arguments to function 'esp_err_t esp_ble_gattc_open(esp_gatt_if_t, uint8_t*, esp_ble_addr_type_t, bool)'
In file included from C:\Users\Max\Documents\Arduino\libraries\ESP32_BLE_Arduino\src\BLEClient.cpp:13:0:
C:\Program Files (x86)\Arduino\hardware\espressif\esp32/tools/sdk/include/bluedroid/esp_gattc_api.h:294:11: note: declared here
esp_err_t esp_ble_gattc_open(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bda, esp_ble_addr_type_t remote_addr_type, bool is_direct);
^exit status 1
Seems like some problem with the library version: https://github.com/espressif/arduino-esp32/issues/1299
What Version of Arduino are you using? I am using 1.8.5 on a iMac with macOS High Sierra Vers. 10.13.4
I just downloaded your source from GitHub. Created a complete new directory as Arduino ANCS_TEST. In this directory i copied your ANCS Folder and the Libraries Folder.
Compiling brings this result:
/Users/krewtib/Documents/Arduino ESP32 ANCS_TEST/ANCS/ANCS.ino:10:18: fatal error: Task.h: No such file or directory
compilation terminated.
exit status 1
Error compiling for board ESP32 Dev Module.
This is a error i really cannot understand as the files Task.h and Task.cpp are in your Libraries Folder.
Funny ain’t it?
Am 22.05.2018 um 20:28 schrieb S-March notifications@github.com:
I don't have my full project (more than just ANCS) done yet, but I pulled out the ANCS portion of it. This code works for me on an esp32 module. I uploaded it to a module just now to verify and it is working.
https://github.com/S-March/esp32_ANCS https://github.com/S-March/esp32_ANCS
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-391093786, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wsC1lIoQv1yZ_Yb_7mAzfO0CE3COks5t1FjFgaJpZM4SlAVo.
@krewtib You should put the cpp and h files into a folder in your library directory like: Arduino\libraries\ESP32_BLE_Arduino
It works! 😄
I am getting notifications from my iPhone. Thank you so much, @S-March !
These are changes needed for the latest ESP32 core:
In File BLEDescriptor.cpp replace:
m_bleUUID.equals(BLEUUID(param->add_char_descr.char_uuid)) &&
with:
m_bleUUID.equals(BLEUUID(param->add_char_descr.descr_uuid)) &&
In file BLEClient.cpp replace;
errRc = ::esp_ble_gattc_open(
getGattcIf(),
*getPeerAddress().getNative(), // address
1 // direct connection
);
with:
errRc = ::esp_ble_gattc_open(
getGattcIf(),
*getPeerAddress().getNative(), // address
BLE_ADDR_TYPE_PUBLIC,
1 // direct connection
);
Fantastic! Glad it works. Let me know if future questions come up.
@Max
Are you sure that these are the only files to be changed?
As soon as i change In File BLEDescriptor.cpp
„add_char_descr.char_uuid" to „add_char_descr.descr_uuid" i get compiler errors.
Am 22.05.2018 um 21:09 schrieb Max K notifications@github.com:
m_bleUUID.equals(BLEUUID(param->add_char_descr.descr_uuid)) &&
@krewtib Only these two files. I installed the ESP32 Arduino core just yesterday so it should be the latest version. Attached is a zip folder with the files that are working for me:
ANCS Arduino.zip
@Max
Now i am fully confused. Please just tell me where to copy which directories.
Must i have the ESP32_BLE_Arduino in my Sketch Folder Libraries or in the Contents/Java/hardware/espressif/esp32/libraries or in both ? Only in the Core gives errors regarding Task.h
Am 22.05.2018 um 22:02 schrieb Max K notifications@github.com:
@krewtib https://github.com/krewtib Only these two files. I installed the ESP32 Arduino core just yesterday so it should be the latest version. Attached is a zip folder with the files that are working for me:
ANCS Arduino.zip https://github.com/nkolban/esp32-snippets/files/2028346/ANCS.Arduino.zip
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-391121795, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wvcElZZ_t8gLpumUg5hIKugrbNVtks5t1G7EgaJpZM4SlAVo.
@krewtib Just noticed you are on a Mac but it should be the same as in Windows:
Folder ESP32_BLE_Arduino needs to be in "documents/Arduino/libraries"
Folder ANCS in "documents/Arduino"
Sorry that doesn’t work.
I have a Folder named Arduino ESP32 ANCS_Test where i have to put my Sketch folder ANCS with ANC.ino in it. Within This folder (Arduino ESP32 ANCS_TEST) i have a folder call libraries where i can put my Arduino libs like SSD1306_lib or TaskScheduler.
My main Arduino.App is in my Application folder and here i have the folders Contents/Java/hardware/espressif/esp32/libraries.
As soon as i put the ESP32_BLE_Arduino folder im my Sketch folder libraries i get compile errors.
I copied the ESP32_BLE_Arduino folder into Contents/Java/hardware/espressif/esp32/libraries and compiled my existing Sketches. Worked.
But compiling ANCS.ino gives errors.
(Documents/Arduino ESP32 ANCS_TEST/ANCS/ANCS.ino:10:18: fatal error: Task.h: No such file or directory
compilation terminated.)
Am 22.05.2018 um 23:01 schrieb Max K notifications@github.com:
@krewtib https://github.com/krewtib Just noticed you are on a Mac but it should be the same as in Windows:
Folder ESP32_BLE_Arduino needs to be in "documents/Arduino/libraries"
Folder ANCS in "documents/Arduino"—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-391139428, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wqi8SAEJ19VpLXHw_sfhn3AEXK2pks5t1Hy4gaJpZM4SlAVo.
I have never placed libraries inside the folder of the current sketch.
There should be a libraries folder in documents/Arduino/
If you install libraries via the Arduino IDE library manager, where do they usually go?
In this case they go into the /Arduino ESP32 ANCS_TEST/Libraries.
I use these Libraries directories in the sketch folders as i can separate them according to my Arduino applications and don’t have a huge Lib directory.
Am 22.05.2018 um 23:28 schrieb Max K notifications@github.com:
I have never placed libraries inside the folder of the current sketch.
There should be a libraries folder in documents/Arduino/
If you install libraries via the Arduino IDE library manager, where do they usually go?—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-391146757, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wq1sPb1BWOOTyzeerb4F3z-NBHuhks5t1ILugaJpZM4SlAVo.
Including libraries in the sketch folder does not work for me at all.
Have you tried using the full path to the source files like: #include "Libraries/ESP32_BLE_Arduino/Task.h"
Will give it try tomorrow.
Von meinem iPad gesendet
Am 23.05.2018 um 00:03 schrieb Max K notifications@github.com:
Including libraries in the sketch folder does not work for me at all.
Have you tried using the full path to the source files like: #include "Libraries/ESP32_BLE_Arduino/Task.h"—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
I've made some progress today with retrieving the notification content:
In addition to the category the Host also sends the UID of the notification. This can be used to request more details such as app and title. For example:
const uint8_t v[]={0x0, ID[0],ID[1],ID[2],ID[3], 0x5};
pControlPointCharacteristic->writeValue((uint8_t*)v,6,true);
This is the output after requesting app, title, content and date:
New notification!
Category: Other
Requesting details...
Notify callback for characteristic 22eac6e9-24d6-4bb5-be44-b36ace7c7bfb of data length 26
0 17 0 0 0 0 12 0 com.apple.podcasts
Notify callback for characteristic 22eac6e9-24d6-4bb5-be44-b36ace7c7bfb of data length 8
0 17 0 0 0 1 0 0
Notify callback for characteristic 22eac6e9-24d6-4bb5-be44-b36ace7c7bfb of data length 114
0 17 0 0 0 3 6A 0 Es gibt eine neue Folge „Stuff You Should Know“, SYSK Selects: Is brain size related to intelligence?.
Notify callback for characteristic 22eac6e9-24d6-4bb5-be44-b36ace7c7bfb of data length 23
0 17 0 0 0 5 F 0 20180519T190930
S-March already implemented the callback for receiving the requested data.
It is working perfectly fine but my code is kind of a mess. I didn't know where to put the request other than in the myclient class. The code is running in a loop, waiting for NotificationSourceNotifyCallback to set a flag:
/** END ANCS SERVICE **/
delay(1000);
while(1){
if(pendingNotification == true){
// CommandID: CommandIDGetNotificationAttributes
// 32bit uid
// AttributeID
Serial.println("Requesting details...");
const uint8_t vIdentifier[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x0};
pControlPointCharacteristic->writeValue((uint8_t*)vIdentifier,6,true);
const uint8_t vTitle[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x1, 0x0, 0x10};
pControlPointCharacteristic->writeValue((uint8_t*)vTitle,8,true);
const uint8_t vMessage[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x3, 0x0, 0x10};
pControlPointCharacteristic->writeValue((uint8_t*)vMessage,8,true);
const uint8_t vDate[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x5};
pControlPointCharacteristic->writeValue((uint8_t*)vDate,6,true);
pendingNotification = false;
}
delay(100); //does not work without small delay
}
Any ideas how this could be improved?
Another major problem is that reconnects don't work. The ESP32 can only connect to the iPhone once. When the connection was lost, the devices have to be paired again.
@Max K
just tried #include "Libraries/ESP32_BLE_Arduino/Task.h“. Didn’t work so i changed to #include "/Applications/Arduino.app/Contents/Java/hardware/espressif/esp32/libraries/BLE/src/Task.h“. This did it.
But there is a new error:
/Documents/Arduino ESP32 ANCS_TEST/ANCS/ANCS.ino: In member function 'virtual void MyServerCallbacks::onConnect(BLEServer*)':
ANCS:176: error: 'm_remoteBda' is not a member of 'BLEDevice'
Serial.println(BLEAddress(BLEDevice::m_remoteBda).toString().c_str());
^
ANCS:180: error: 'm_remoteBda' is not a member of 'BLEDevice'
pMyClient->start(new BLEAddress(BLEDevice::m_remoteBda));
^
exit status 1
'm_remoteBda' is not a member of ‚BLEDevice'
Am 23.05.2018 um 22:51 schrieb Max K notifications@github.com:
I've made some progress today with retrieving the notification content:
In addition to the category the Host also sends the UID of the notification. This can be used to request more details such as app and title. For example:const uint8_t v[]={0x0, ID[0],ID[1],ID[2],ID[3], 0x5};
pControlPointCharacteristic->writeValue((uint8_t*)v,6,true);
This is the output after requesting app, title, content and date:New notification!
Category: Other
Requesting details...
Notify callback for characteristic 22eac6e9-24d6-4bb5-be44-b36ace7c7bfb of data length 26
0 17 0 0 0 0 12 0 com.apple.podcasts
Notify callback for characteristic 22eac6e9-24d6-4bb5-be44-b36ace7c7bfb of data length 8
0 17 0 0 0 1 0 0
Notify callback for characteristic 22eac6e9-24d6-4bb5-be44-b36ace7c7bfb of data length 114
0 17 0 0 0 3 6A 0 Es gibt eine neue Folge „Stuff You Should Know“, SYSK Selects: Is brain size related to intelligence?.
Notify callback for characteristic 22eac6e9-24d6-4bb5-be44-b36ace7c7bfb of data length 23
0 17 0 0 0 5 F 0 20180519T190930S-March already implemented the callback for receiving the requested data.
It is working perfectly fine but my code is kind of a mess. I didn't know where to put the request other than in the myclient class. The code is running in a loop, waiting for NotificationSourceNotifyCallback to set a flag:/* END ANCS SERVICE */
delay(1000);
while(1){
if(pendingNotification == true){
// CommandID: CommandIDGetNotificationAttributes
// 32bit uid
// AttributeID
Serial.println("Requesting details...");
const uint8_t vIdentifier[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x0};
pControlPointCharacteristic->writeValue((uint8_t)vIdentifier,6,true);
const uint8_t vTitle[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x1, 0x0, 0x10};
pControlPointCharacteristic->writeValue((uint8_t)vTitle,8,true);
const uint8_t vMessage[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x3, 0x0, 0x10};
pControlPointCharacteristic->writeValue((uint8_t)vMessage,8,true);
const uint8_t vDate[]={0x0, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x5};
pControlPointCharacteristic->writeValue((uint8_t)vDate,6,true);
pendingNotification = false;
}
delay(100); //does not work without small delay
}
Any ideas how this could be improved?—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-391491904, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wofJokAZj6lCEdK3Q3c1T24EE8kwks5t1cu6gaJpZM4SlAVo.
@krewtib There has to be a simpler solution to your problem. It's very strange that you have to include the task.h in this complicated way.
@Max
Thanks a lot for your help and the time you spent on my problem. But i give up this project. I think it is not worth investing that much effort. Maybe someday someone has a solution for Mac OS X then i’ll dig it out again. I am going to return to the modules that i have running. Thanks again.
Am 24.05.2018 um 14:49 schrieb Max K notifications@github.com:
@krewtib https://github.com/krewtib There has to be a simpler solution to your problem. It's very strange that you have to include the task.h in this complicated way.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-391702414, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wkEOR0sBHbd60jlEoFHW-fvAKozeks5t1qxrgaJpZM4SlAVo.
@S-March @CoretechR I tried your working code and it compiles but occupies around 94% flash memory. Is there anything we can do to reduce the sketch size without affecting the ANCS functionality?
This is a really important issue to solve since ANCS is not the only thing that ESP32 can do. If anyone can give some guidance to lighten the footprint, that would be very helpful. Thanks.
@dominicklee You can change partition size, change debug log level to NONE, or switch Partition scheme to No OTA
@dominicklee, what @chegewara is correct. It is actually not so much the ANCS portion of the code that takes up so much space, but the BLE stack. I have a current project using this + the wifi stack for OTA but it requires a custom partitioning of the flash to basically have no SPIFFS available.
I agree with you guys. However, given that a wearable can do many things, how can we either lighten up the ESP32 BLE stack or add more flash to increase memory size?
At this rate, the microcontroller is so occupied that it becomes incapable of running anything else.
You can find ESP32 wroover with more than 4MB flash (8 or 16MB versions).
https://www.analoglamb.com/product/alb32-wrover-esp32-module-with-64mb-flash-and-32mb-psram/
With esp-idf you can turn off not used modules ble server or ble client. You can try to make some sdkconfig tweaks but i dont know if it will help, never been trying with arduino.
A friend trying a BLE Scanner + WiFi also ran out of space and he pushed me to this URL:
http://www.instructables.com/id/Nano-ESP32-BLE-Scanner/
The above tailor-made arduino-esp32 source extended the app partition to 0x1800000 to fit BLE and WiFi logic in the same program. If you already have Arduino with ESP32 support, some files require to modify manually.
I tried it and it worked well.
Am 24.05.2018 um 20:27 schrieb chegewara notifications@github.com:
You can find ESP32 wroover with more than 4MB flash (8 or 16MB versions).
https://www.analoglamb.com/product/alb32-wrover-esp32-module-with-64mb-flash-and-32mb-psram/ https://www.analoglamb.com/product/alb32-wrover-esp32-module-with-64mb-flash-and-32mb-psram/
With esp-idf you can turn off not used modules ble server or ble client. You can try to make some sdkconfig tweaks but i dont know if it will help, never been trying with arduino.
You can try this command in setup(very first command):
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
again, i never been trying with arduino.—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-391814098, or mute the thread https://github.com/notifications/unsubscribe-auth/Ah03wmQAruN-EhMqAmTk3qlJZ6sbvtPuks5t1vuGgaJpZM4SlAVo.
Thanks for your inputs! Will try that and update you guys.
@S-March, do you have the same issue with the ESP32 not reconnecting after the connection was lost? It's really the only problem left with the ANCS example.
@CoretechR, yeah I don't seem to have any issues with it reconnecting. Make sure you have an advertising callback on disconnect.
@S-March There is a callback:
void onDisconnect(BLEServer* pServer) {
Serial.println("************************");
Serial.println("**Device disconnected**");
Serial.println("************************");
}
};
After the first disconnect this is the output:
Device connected
6a:ae:04:c6:9d:fc
E (19875) BT: lmp_version_below LMP version 6 < 8
E (19876) BT: earlier enc was not done for same deviceE (20052) BT: l2cble_start_conn_update, the last connection update command still pending.
E (21033) BT: bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0008
E (21034) BT: bta_gattc_conn_cback() - cif=5 connected=0 conn_id=5 reason=0x0008
Device disconnected
And this goes on forever.
Hmmm, I may need to take a look. I think all you would need to do would be add a
'''
//Start advertising
pAdvertising->start();
'''
Into that callback.
Into the disconnect callback?
I am using the exact code you provided. So if your reconnects work that would mean that there is something wrong with the ESP32 core or the hardware.
EDIT: I tried the ANCS sketch with an older version of the ESP32 Arduino core. This way I can use your code without any changes. It still goes into a connect-disconnect-loop. I am out of ideas.
Gentlemen, I am glad to say that I got the ANCS to work with my iPhone as well.
I have a couple of follow-up questions that I hope you experts can help:
What code should I add to the existing ANCS example to make it show the details of a notification in a String variable or char array (i.e. sender, title, message, etc.) ?
What code should I add to the existing ANCS example to make it respond to an ANCS characteristic of a particular notification (i.e. user accepting or rejecting a call) ?
These ANCS-related questions may be helpful to the library and anyone who is interested in maximizing the ANCS functionality. Hope you guys can help. Thanks again!
@dominicklee This works for retrieving details: #430 (comment)
The example already outputs the notification type, so responding to that should be fairly easy.
By the way: Is your ESP32 able to reconnect to the iPhone after the connection was lost?
@CoretechR Yeah, I saw your comment. However, it seems that some variables were undeclared when I tried implementing it. Could you explain how exactly I can retrieve the notification details in string variables? Or perhaps can you post your updated ANCS example code which prints out the text details of the notifications? That would be helpful.
Btw, yes my iPhone was able to re-establish the connection even after connection was lost. Pls see attached image.

Could anyone also explain why a couple errors shown above were encountered with "bta_gattc" ?
@dominicklee This is the updated code: ANCSdetailed.txt
The strings are handled in dataSourceNotifyCallback
Very strange that the reconnect issue only happens with my ESP32. The output looks exactly like in your screenshot, only followed by a disconnect. Maybe it's hardware related after all? I am using one of these boards:

@CoretechR Thanks for sharing the updated code! I am currently using the WiFi board from Heltec. It seems to work fine even with reconnecting.
By the way, have you figured out what lines of code can be run to either accept or decline a phone call notification? Please shed some light on how that can be achieved.
Thanks in advance!
@dominicklee Haven't tested it but it is described here: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v12.2.0%2Fble_sdk_app_ancs.html
Field | Example value | Interpretation
-- | -- | --
Command ID | 2 | Perform notification action
Notification UID | 01-02-03-04 | 67305985 (0x4030201)
Action | 00/01 | Positive/Negative
Request details with command ID 0, answer with command ID 2. Should be pretty straight forward.
In regards to the reconnect problem, I tried a few more things:
By the way, I am testing this by pairing the ESP32, then turning BT on the iPhone off and on. Going out of range of the ESP32 produces the same result. The next step would be to get another ESP32 module to rule out a hardware problem. But I don't have high hopes.
@CoretechR You are correct. You should get another ESP32 module since it is more likely a hardware problem. I have never experienced your re-connection problem. Your code works fine.
By the way, I put the following code inside the MyClient class to make the iPhone accept a call when the notification is an Incoming call:
const uint8_t vResponse[]={0x02, latestMessageID[0],latestMessageID[1],latestMessageID[2],latestMessageID[3], 0x00};
pControlPointCharacteristic->writeValue((uint8_t*)vResponse,6,true);
However, I want to allow a user to push buttons on the microcontroller that calls this code. I was not able to move this code to void loop() since pControlPointCharacteristic is no longer defined in void loop().
Additionally, when there is an "Incoming Call", the user has a 15 second period to pick up the call. This 15 second period sometimes is longer or shorter depending on the caller. How does the ESP32 still know when the Incoming Call notification period has expired?
For example, we don't want the user to think they can answer call when the call is already gone. Is there a way we can get a boolean that indicates "Incoming call"? That boolean should be true when someone is calling and false when there is no call.
@dominicklee The eventID can signify three types of notifications:
EventIDNotificationAdded | = 0
-- | --
EventIDNotificationModified | = 1
EventIDNotificationRemoved | = 2
After the call is missed, a notification with EventIDNotificationRemoved is triggered. This should be reliable. To test this you can remove if(pData[0]==0) and include this output in the ANCS example:
if(pData[0]==0) Serial.println("New notification!");
else if(pData[0]==1) Serial.println("Notification modified!");
else if(pData[0]==2) Serial.println("Notification removed!");
@CoretechR Okay, so pData[0] contains the eventID. With that, I can update a boolean accordingly. Thank you for the insights. That is brilliant!
Fantastic- this is really helpful, thank you! I’ve made a smartwatch for ESP32 myself that is up on my GitHub, but without ANCS yet.
@jhud glad I could help! I actually built the library for that exact purpose. I am almost done with mine, just some last minute tweaks to how it handles OTA's and then I'll update the repo and open source it for everyone!
I just tried the original ANCS example by S-March on a brand new Sparkfun ESP32 board and the reconnect-problem still persists.
Two ESP32 modules, different computers, iOS devices and Arduino core versions, nothing works. 🙁
This is now working for me - I can receive notifications from my iPhone on the ESP32 :). It wasn't working a couple of weeks ago, but I just pulled the latest ESP32-arduino repo, and the error about exceptions has gone away. The Task.cpp/.h patch doesn't seem to be needed anymore. Thank you for putting this code out there - I'll start on some code to retrieve the notification text from iOS, and then share it.
@jhud Great that it's working for you now. Would you mind sharing the library files that you are using?
I just tried the original code and library files by S-March and I am getting various errors.
@CoretechR I just found this Page while trying to get the Ancs service to work on my esp32.
Just Installed the newest Arduino IDE with the newest ESP core (from Boards manager) and can´t get it to work without any errors (and if it compiles, the ESP does nothing ?!).
Does anyone know how to get this to work ? want to make a Notification TFT display for whatsapp etc.
Hello @S-March, first, thank you for sharing your code. I'm also trying to do a swartwatch so your code will be really useful.
However, after everything was correctIy setup (I followed @CoretechR instructions) I encountered an issue : my phone (iPhone 6) doesn't detect the bluetooth device. I even tryied with the nRF app and there is no device that corresponds.
Here is what I got on the serial monitor :
ets Jun 8 2016
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:808
load:0x40078000,len:6084
load:0x40080000,len:6696
entry 0x400802e4
Do you have an idea of where this come from ?
Looks like a brown out. Make sure you have a power supply that can provide enough current!
I just tried with a 5V 2A external power supply while uploading the code and I still get no new device recognized on my phone.
Also the previous message was get after I pressed the reset button and I still get the same result.
Great project! Thanks alot for the efforts and for sharing @S-March !
I'm trying to compile the code from the repository for a lolin d32 but get the following error message:
/Users/mh/Documents/Arduino/libraries/ANCS/BLEServer.cpp:21:22: fatal error: gatt_api.h: No such file or directory
I copied the files from the Library Folder from your repo to a subfolder in the Arduino libraries folder.
Googling "gatt_api.h" points to a file in the espressif repository which does not exist anymore (to here).
I have installed vesion 1.0.0 of espressifs esp32 board definitions.
Any idea how to resolve this?
@m-hertig There is old ble library included in project. You can download files from this repository and replace in ANCS project.
Thank you for the reply @chegewara !
Well I use the files from the Library folder in the ANCS project but still get that error. Might there be a version conflict with the rest my esp32 library?
I know what files you are using. The thing is that since then there was change in esp-idf and file name has changed from gatt_api.h to esp_gatt_api.h (i think).
The file is now named esp_gatts_api.h but even with that there are still errors. I just tried the latest esp32 core and library versions and nothing works. @S-March , do you have a working ANCS example with the latest software versions?
I got it working now using the current version of the ESP32_BLE_Arduino library and then manually doing the modifications that @S-March described in the posts above. Here is the code that works for me:
ANCS_ESP32.zip
Thanks alot for the good work!
first, thanks @m-hertig for the Update!
I tried out your Code and the Libs, but it won´t run correctly.
Does someone know whats going on here?
(I can see the ESP within the iOS BT Settings & can connect, but after this I get a reboot, see code)
`ets Jun 8 2016 00:22:57
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:952
load:0x40078000,len:6084
load:0x40080000,len:7936
entry 0x40080310
Device connected
42:ac:a7:e0:bc:1a
CORRUPT HEAP: Bad head at 0x3fff5400. Expected 0xabba1234 got 0x3fff5408
E (102133) boot: Assert failed in multi_heap_free, /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/heap/multi_heap_poisoning.c:205 (head != NULL)
Guru Meditation Error: Core 0 panic'ed (Interrupt wdt timeout on CPU0)
Core 0 register dump:
PC : 0x400d94cd PS : 0x00060334 A0 : 0x80090884 A1 : 0x3ffdcce0
A2 : 0x3ffc334c A3 : 0x000000cd A4 : 0x3ffc3410 A5 : 0x3ffc333c
A6 : 0x00060f23 A7 : 0x00000000 A8 : 0x800d94cd A9 : 0x3ffdcc90
A10 : 0x40158110 A11 : 0x3ffc7f58 A12 : 0x3f401dd8 A13 : 0x00000000
A14 : 0x00000001 A15 : 0x00000001 SAR : 0x00000004 EXCCAUSE: 0x00000005
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xfffffffc
Backtrace: 0x400d94cd:0x3ffdcce0 0x40090881:0x3ffdcd10 0x40084b3e:0x3ffdcd30 0x4008a3f9:0x3ffdcd50 0x4000bec7:0x3ffdcd70 0x4016f3d1:0x3ffdcd90 0x40172a5a:0x3ffdcdb0 0x400d6b72:0x3ffdcdd0 0x400d4304:0x3ffdce10 0x400d4c71:0x3ffdce50 0x400d373d:0x3ffdce70 0x400d4131:0x3ffdcf20 0x400e1894:0x3ffdcf70 0x400e1bb6:0x3ffdcfb0 0x400ddf41:0x3ffdcfd0
Core 1 register dump:
PC : 0x4008db3d PS : 0x00060034 A0 : 0x800901be A1 : 0x3fff2ed0
A2 : 0x3ffaffb4 A3 : 0x0000abab A4 : 0xb33fffff A5 : 0x00000001
A6 : 0x00060020 A7 : 0x0000cdcd A8 : 0x0000cdcd A9 : 0x3fff2ed0
A10 : 0x00000003 A11 : 0x00060023 A12 : 0x00060020 A13 : 0x3fff3174
A14 : 0x3fff3138 A15 : 0x3f41346c SAR : 0x00000010 EXCCAUSE: 0x00000005
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xfffffffe
Backtrace: 0x4008db3d:0x3fff2ed0 0x400901bb:0x3fff2f00 0x40090833:0x3fff2f20 0x40084a44:0x3fff2f40 0x40084a75:0x3fff2f60 0x4008a3ed:0x3fff2f80 0x4000beaf:0x3fff2fa0 0x4016f40f:0x3fff2fc0 0x40172a49:0x3fff2fe0 0x40172c97:0x3fff3000 0x4017053e:0x3fff3030 0x401707ce:0x3fff3070 0x401a05d9:0x3fff3090 0x40170abd:0x3fff30b0 0x40170b5d:0x3fff30d0 0x40170c25:0x3fff3100 0x400d647f:0x3fff3120 0x400d433b:0x3fff3220 0x400d179d:0x3fff3280 0x400d6c86:0x3fff32c0
Rebooting...
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:952
load:0x40078000,len:6084
load:0x40080000,len:7936
entry 0x40080310
`
First Thank you so much for this ANCS code @S-March.
I am having difficulties getting a notification's "appID" using the control point characteristic.
example. "com.apple.facetime"
This is my current understanding of how I can obtain that information.
Once a notification has be received I get the notificationUID and pass it into the control point characteristic's write value function. Based off of the ANCS documentation site, the format should be [commandID-notificationUID-attributeID].
From this threads ANCS code, I declared the pControlPointCharatersitic globally & statically (instead of inside of the myClient class) but when we use the writevalue() function it hangs. Is there another approach to obtain ALL OF the notification's information?
example of how I am currently trying to implement it.
[D][BLERemoteCharacteristic.cpp:554] writeValue(): >> writeValue(), length: 11
[D][FreeRTOS.cpp:164] take(): Semaphore taking: name: WriteCharEvt (0x3fff5a24), owner:for writeValue
[D][FreeRTOS.cpp:173] take(): Semaphore taken: name: WriteCharEvt (0x3fff5a24), owner: writeValue
@tccox3 I have a working exaple of showing notification with App ID, i can upload this for you.
But can someone tell me how can I put the Nofification etc. into a variable that can be printed out on a TFT etc? String or Char Array?
The default is a byte Stream that gets print out with the Serial.Write function...
I actually got the ANCS code running on my ESP32 smartwatch today. It’s working great, and I’m getting notifications no problem. Thanks for the comments posted here! You can find it in my public repo, but it all needs a big refactor when I have time.
@jhud Thank you for Posting your good work!
I have still problems with reconnecting to the device when its reset. are there any ways to make a reconnect possible ( iPhone turn On/Off BT Or ESP Lost Power ).
Most helpful comment
I don't have my full project (more than just ANCS) done yet, but I pulled out the ANCS portion of it. This code works for me on an esp32 module. I uploaded it to a module just now to verify and it is working.
https://github.com/S-March/esp32_ANCS
Let me know if you guys run into any issues.