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!

CoretechR commented 6 years ago

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

krewtib commented 6 years ago

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.

CoretechR commented 6 years ago

@krewtib You should put the cpp and h files into a folder in your library directory like: Arduino\libraries\ESP32_BLE_Arduino

CoretechR commented 6 years ago

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

Fantastic! Glad it works. Let me know if future questions come up.

krewtib commented 6 years ago

@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)) &&

CoretechR commented 6 years ago

@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

krewtib commented 6 years ago

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

CoretechR commented 6 years ago

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

krewtib commented 6 years ago

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.

CoretechR commented 6 years ago

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?

krewtib commented 6 years ago

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.

CoretechR commented 6 years ago

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"

krewtib commented 6 years ago

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.

CoretechR commented 6 years ago

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.

krewtib commented 6 years ago

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

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

CoretechR commented 6 years ago

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

krewtib commented 6 years ago

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

dominicklee commented 6 years ago

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

chegewara commented 6 years ago

@dominicklee You can change partition size, change debug log level to NONE, or switch Partition scheme to No OTA

S-March commented 6 years ago

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

dominicklee commented 6 years ago

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.

chegewara commented 6 years ago

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.

krewtib commented 6 years ago

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.

dominicklee commented 6 years ago

Thanks for your inputs! Will try that and update you guys.

CoretechR commented 6 years ago

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

S-March commented 6 years ago

@CoretechR, yeah I don't seem to have any issues with it reconnecting. Make sure you have an advertising callback on disconnect.

CoretechR commented 6 years ago

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

E (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.

S-March commented 6 years ago

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.

CoretechR commented 6 years ago

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.

dominicklee commented 6 years ago

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:

  1. 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.) ?

  2. 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!

CoretechR commented 6 years ago

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

dominicklee commented 6 years ago

@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. ancs-serial-github

dominicklee commented 6 years ago

Could anyone also explain why a couple errors shown above were encountered with "bta_gattc" ?

CoretechR commented 6 years ago

@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: doit-esp-wroom-32-devkit

dominicklee commented 6 years ago

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

CoretechR commented 6 years ago

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

CoretechR commented 6 years ago

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.

dominicklee commented 6 years ago

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

CoretechR commented 6 years ago

@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!");
dominicklee commented 6 years ago

@CoretechR Okay, so pData[0] contains the eventID. With that, I can update a boolean accordingly. Thank you for the insights. That is brilliant!

jhud commented 6 years ago

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.

S-March commented 6 years ago

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

https://github.com/S-March/smarchWatch_PUBLIC

CoretechR commented 6 years ago

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

jhud commented 6 years ago

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.

CoretechR commented 6 years ago

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

Petros144 commented 5 years ago

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

t-ptf commented 5 years ago

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 ?

S-March commented 5 years ago

Looks like a brown out. Make sure you have a power supply that can provide enough current!

t-ptf commented 5 years ago

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.