nkolban / esp32-snippets

Sample ESP32 snippets and code fragments
https://leanpub.com/kolban-ESP32
Apache License 2.0
2.33k stars 709 forks source link

ANCS library #430

Closed S-March closed 6 years ago

S-March commented 6 years ago

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!

chegewara commented 6 years ago

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?

S-March commented 6 years ago

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?

chegewara commented 6 years ago

Can you provide some logs?

S-March commented 6 years ago

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
E (58047) BT: lmp_version_below LMP version 6 < 8
E (58316) BT: Call back not found for application conn_id=3
[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!
E (59996) BT: FOR LE SC LTK IS USED INSTEAD OF STK
[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!
chegewara commented 6 years ago

2 questions:

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
S-March commented 6 years ago

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:

  1. Forced phone to forget device
  2. Booted ESP
  3. Opened settings panel on phone
  4. Found device and hit connect
  5. When pairing pop up showed up, I hit pair
  6. Turned off BT on phone to force a disconnect
  7. Turned BT back on and reconnected to ESP

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
E (9791) BT: lmp_version_below LMP version 6 < 8
E (10179) BT: Call back not found for application conn_id=3
[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!
E (12699) BT: FOR LE SC LTK IS USED INSTEAD OF STK
[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!
E (19996) BT: bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0013
[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
E (25958) BT: lmp_version_below LMP version 6 < 8
E (26137) BT: l2cble_start_conn_update, the last connection update command still pending.
[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!
E (26686) BT: Call back not found for application conn_id=3
[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!
chegewara commented 6 years ago

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.

S-March commented 6 years ago

Oh, interesting. I will try that in the morning! Thanks, will report back

S-March commented 6 years ago

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!

chegewara commented 6 years ago

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]

S-March commented 6 years ago

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.

S-March commented 6 years ago

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);

chegewara commented 6 years ago

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.

S-March commented 6 years ago

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?

chegewara commented 6 years ago

Yes, it sounds good.

S-March commented 6 years ago

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?

chegewara commented 6 years ago

Check if this static esp_bd_addr_t m_remoteBda; is private or public. Needs to be public static.

S-March commented 6 years ago

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());

chegewara commented 6 years ago

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
S-March commented 6 years ago

New and exciting error!

error: invalid array assignment BLEDevice::m_remoteBda=param->connect.remote_bda;

chegewara commented 6 years ago

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.

S-March commented 6 years ago

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
S-March commented 6 years ago

Back to work on the rest of the library, will continue to update as I make progress.

S-March commented 6 years ago

image

Wooo! Client is connecting and found the characteristics on phone!

Next step is to ID those notifications and make use of them!

S-March commented 6 years ago

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);
}
chegewara commented 6 years ago

Nice work. You can create new project on github with this project, its your project, and then you can share with community on forum.

S-March commented 6 years ago

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 :)

chegewara commented 6 years ago

@S-March What IOS do you have on iPhone 8?

S-March commented 6 years ago

I’m running on 11.2.6

krewtib commented 6 years ago

@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?

S-March commented 6 years ago

@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.

chegewara commented 6 years ago

There is no Task class in arduino library. You can try to copy it, but i dont remember if it works in arduino environment.

S-March commented 6 years ago

This is what I used: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/Task.h

krewtib commented 6 years ago

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.

S-March commented 6 years ago

Take a look at the very first post in this thread, I created a setServiceSolicitation() in BLEAdvertising.h

krewtib commented 6 years ago

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.

S-March commented 6 years ago

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_ */
krewtib commented 6 years ago

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.

S-March commented 6 years ago

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

krewtib commented 6 years ago

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.

S-March commented 6 years ago

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.

krewtib commented 6 years ago

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


E (32000) BT: lmp_version_below LMP version 6 < 8 E (32002) BT: btc_gattc_call_handler() E (32005) BT: l2cble_start_conn_update, the last connection update command still pending. E (32014) BT: earlier enc was not done for same device  E (32387) BT: Call back not found for application conn_id=3 E (32387) BT: Call back not found for application conn_id=5 E (34066) BT: bta_gattc_cmpl_cback unknown conn_id = 3, ignore data


this after disconnecting


Device disconnected


E (65057) BT: Device not found  E (65058) BT: bta_gattc_mark_bg_conn unable to find the bg connection mask for: 6c:c1:60:95:0d:53

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.

CoretechR commented 6 years ago

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?

chegewara commented 6 years ago

https://github.com/nkolban/esp32-snippets/issues/430#issuecomment-389659442

CoretechR commented 6 years ago

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.

krewtib commented 6 years ago

@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 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 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.

CoretechR commented 6 years ago

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.

chegewara commented 6 years ago

It would be nice if @S-March could share his code as he promissed.

krewtib commented 6 years ago

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.

S-March commented 6 years ago

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.