Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Built with ESP32 not-nimble? #10

Closed
sdetweil opened this issue May 1, 2023 · 19 comments
Closed

Built with ESP32 not-nimble? #10

sdetweil opened this issue May 1, 2023 · 19 comments
Assignees
Labels
question Further information is requested

Comments

@sdetweil
Copy link
Contributor

sdetweil commented May 1, 2023

I have a crash when using Nimble instead of the normal ESP32 libs..
h2zero/NimBLE-Arduino#530
basically I need to change the UUID of my service.
with ArduinoBLE I had to destroy the whole setup and rebuild to do that

that works with ESP32 BLE.
doesn't work with NIMBLE

but I also need OTA on the ESP32-DevKitv1.

have u tried to build this with the base esp32 lib?

@vovagorodok
Copy link
Owner

vovagorodok commented May 1, 2023

have u tried to build this with the base esp32 lib?

About "base esp32 lib" You mean ArduinoBLE or esp32 bluetooth c-style libraries?
I have tested with ArduinoBLE and NimBle libraries. By default is ArduinoBLE. If You use NimBle please add flag USE_NIM_BLE_ARDUINO_LIB.

Currently I can't understand usecase. Please give me more information how ArduinoBleOTA should work in Your project

@vovagorodok vovagorodok changed the title built with ESP32 not-nimble? Built with ESP32 not-nimble? May 1, 2023
@sdetweil
Copy link
Contributor Author

sdetweil commented May 1, 2023

I have an ESP32 device, it uses BLE to advertise (as server). the UUID(1st 8 chars) has meaning
during the execution, a sensor changes value, and the UUID changes.
(using UUID instead of characteristic as multiple phones need to know the UUID value.. if connected, no other device can see it.
so as server, I have to stop service, server... and restart to change the UUID. Nimble crashes. (reboots)

anyhow using the official Arduino supplied (via Espressif) from https://github.com/nkolban/ESP32_BLE_Arduino
pre Nimble

@vovagorodok
Copy link
Owner

vovagorodok commented May 1, 2023

If I correctly understand, value of a sensor is a part of service uuid. When sensor value changes, uuid changes according to it (1st 8 chars). Than you can broadcast value via advertising to more than one devices. Not sure if there no better way to do that in BLE.

Maybe this example can help You:
https://github.com/vovagorodok/ArduinoBleOTA/blob/main/examples/multiservice/main.ino

#include <ArduinoBleOTA.h>
#include <BleOtaMultiservice.h>

#define NAME "MultiSrv"
#ifndef USE_NIM_BLE_ARDUINO_LIB
using BleString = std::string;
#else
using BleString = String;
#endif

BleString serviceWithValueInUuid = "<initial value>";

void setup() {
  initBle(NAME);

  ArduinoBleOTA.begin(InternalStorage);
  advertiseBle(NAME, serviceWithValueInUuid);
}

void loop() {
  if (<sensor value changed>) {
    serviceWithValueInUuid = <new uuid with value>;
    advertiseBle(NAME, serviceWithValueInUuid);
  }

#ifndef USE_NIM_BLE_ARDUINO_LIB
  BLE.poll();
#endif
  ArduinoBleOTA.pull();
}

@sdetweil
Copy link
Contributor Author

sdetweil commented May 1, 2023

and there are characteristics too and I need the 'service' UUID to be stable as I am caching the characteristic UUIDs to speed up other functions..

get some config data
get my sw version info
turn on LED
turn off relay

advertiseBle

where did that come from?

I don't see it in Nimble, ArduinoBle or ESP32 BLE.

@vovagorodok
Copy link
Owner

where did that come from?

It's from additional ArduinoBleOTA utils in <BleOtaMultiservice.h> that helps to use BleOta with additional services

@sdetweil
Copy link
Contributor Author

sdetweil commented May 1, 2023

thx.. I see what you did

nline bool advertiseBle(const char* deviceName,
                         const char* secondaryUUID)
{
    return advertiseBle(deviceName, BLE_OTA_SERVICE_UUID, secondaryUUID);
}

does your code/sender depend on the OTA service UUID being 1st?. right now my apps depend on that ..

@vovagorodok
Copy link
Owner

No, BLE_OTA_SERVICE_UUID can be secondaryUUID

@sdetweil
Copy link
Contributor Author

sdetweil commented May 1, 2023

looks pretty cool, I'll have to experiment with changing the advertised service.. vs start/stop

so I am replacing this in my existing code with your advertiseBle() equivalent

#ifdef ESP32
  if(pAdvertising == null){
     pAdvertising = BLEDevice::getAdvertising();
     pAdvertising->setScanResponse(true);
  } 
  pAdvertising->addServiceUUID(ourService->getUUID());
 
#else  
  BLE.setAdvertisedService(*ourService);
  BLE.addService(*ourService);
#endif

and adding your service functionality as well..

@sdetweil
Copy link
Contributor Author

sdetweil commented May 4, 2023

like you I createService(UUID)
does the setAdvertisementdata() override that name?

I don't see it change when using my android scanner apps

@vovagorodok
Copy link
Owner

Advertisement data has limited size. If you add to it more than max size, something will be removed from advertisement block. Can it be even name.
In advertiseBle() desided to:

  • in setAdvertisingData() add OTA 128bit UUID and flags
  • in setScanResponseData() add other custom service UUID and name. Max name size with 128 bit UUID is 11. If you write here more than 11 chars, 128 bit UUID wil be removed from block

More about it:
https://novelbits.io/maximum-data-bluetooth-advertising-packet-ble/

@sdetweil
Copy link
Contributor Author

sdetweil commented May 4, 2023

thats gonna be a mess as we both have 128bit UUIDs..

but, at the moment I am only doing mine, to make sure the service UUID switch is correct

@sdetweil
Copy link
Contributor Author

sdetweil commented May 4, 2023

so, using your approach for setting the UUID of the services does not change the UUID as seen by the app store BLE scanners.

here is my adaptation of your code (multiservice) and the code I use to stop/rebuild/restart the service

void changeServiceUUID(const char* deviceName,
                       const char* primaryUUID,
                       const char* secondaryUUID) {
#ifdef ESP32
  #if USE_NIMBLE
    BLEAdvertisementData primaryAdvertisementData {};
    primaryAdvertisementData.setFlags(BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
    primaryAdvertisementData.setCompleteServices(BLEUUID(primaryUUID));
    pAdvertising->setAdvertisementData(primaryAdvertisementData);
    if(secondaryUUID){
      BLEAdvertisementData secondaryAdvertisementData{};
      secondaryAdvertisementData.setShortName(deviceName);
      secondaryAdvertisementData.setCompleteServices(BLEUUID(secondaryUUID));
      pAdvertising->setScanResponseData(secondaryAdvertisementData);
    }
  #else
    BLEAdvertisementData primaryAdvertisementData {};
    primaryAdvertisementData.setFlags(BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
    primaryAdvertisementData.setCompleteServices(BLEUUID(primaryUUID));
    pAdvertising->setAdvertisementData(primaryAdvertisementData);
    if(secondaryUUID){
      BLEAdvertisementData secondaryAdvertisementData{};
      secondaryAdvertisementData.setShortName(deviceName);
      secondaryAdvertisementData.setCompleteServices(BLEUUID(secondaryUUID));
      pAdvertising->setScanResponseData(secondaryAdvertisementData);
    }
  #endif
#else                     }
  BLEAdvertisingData primaryAdvertisementData {};
  primaryAdvertisementData.setFlags(BLEFlagsGeneralDiscoverable | BLEFlagsBREDRNotSupported);
  primaryAdvertisementData.setAdvertisedServiceUuid(primaryUUID);
  BLE.setAdvertisingData(primaryAdvertisementData);
  if(secondaryUUID){
    BLEAdvertisingData secondaryAdvertisementData{};
    secondaryAdvertisementData.setLocalName(deviceName);
    secondaryAdvertisementData.setAdvertisedServiceUuid(secondaryUUID);
    BLE.setScanResponseData(secondaryAdvertisementData);
  }
#endif
}
// restart the service with a new UUID
void restartServices() {
// UseQuick means use the advertismentdata approach
#if UseQuick 
   #ifdef ESP32
     #if USE_NIMBLE
       pAdvertising->stop();  
     #else
       BLEDevice::stopAdvertising();
     #endif
   #else
     BLE.stopAdvertise();
   #endif
   changeServiceUUID(DeviceName.c_str(), makeUUIDString().c_str(),null);
   #ifdef ESP32
     #if USE_NIMBLE
        pAdvertising->start();
     #else
        BLEDevice::startAdvertising();
     #endif
   #else  
     BLE.advertise();
   #endif
   pBLEScanner->start(2 /*scanTimeout/1000*/, true);
#else

  // is the current way, destroy all the functions, service, server...  and rebuild
  #ifdef ESP32
    BLEDevice::stopAdvertising();
      #if USE_NIMBLE
        //  keep the advertising object, just remove the service
        pAdvertising->removeServiceUUID(ourService->getUUID());
      #endif
    pBLEScanner->stop();
    #if USE_NIMBLE == 0
      Sprintln("stopping service");
      ourService->stop();
    #endif
    Sprintln("deleting service");
    delete ourService;
      #if USE_NIMBLE == 0
        // nimble has no deinit on server
        // and no way to remove the service
        Sprintln("deleting server");
        delete pServer;
        pServer = NULL;
      #endif
    Sprintln("sleep a little, 100ms");
    delay(100);
    // create the server/service/characteristics again
    setupService();
    Sprintln("restart advertising after resetup");
    startAdvertising();
  
    Sprintln("after restart advertising after resetup");
  
  #else
    // this is the ArduinoBLE way (nano IOT 33)
    // stop advertising
    BLE.stopAdvertise();
    // disconnect any attached clients (timing is everything!)
    BLE.disconnect();
    // shut down BLE processor
    BLE.end();
    delay(50);
    // delete our service
    delete ourService;
    delay(50);
    // start BLE again
    BLE.begin();
    // create the service and characteristics again
    setupService();
    // and advertise the new info 
    BLE.advertise();
    advertising = true;
    // continue looking for our app uuid
    BLE.scan();  // resume scanning, ble.end killed it
  #endif
#endif
}

@vovagorodok
Copy link
Owner

Hmm, I never need and never try restart ble services. Don't know what happens here. Maybe It's more question to NimBle library experts

@sdetweil
Copy link
Contributor Author

sdetweil commented May 4, 2023

thx.. of course they don't answer

@sdetweil
Copy link
Contributor Author

sdetweil commented May 5, 2023

looking at the nimble bleserver, it had add and remove service...

so at least for me, I can add another characteristic to start the ota service advertising and then your stuff works. on reboot, my service would be started. and I don't need multi service...

and I can create my two services and toggle between them. the characteristics would be shared between them

do you have a library function to create your service definition?

@sdetweil sdetweil closed this as completed May 5, 2023
@sdetweil sdetweil reopened this May 5, 2023
@vovagorodok
Copy link
Owner

vovagorodok commented May 6, 2023

do you have a library function to create your service definition?

No, it's just only singleton instance. As I understand you need start OTA with other UUIDs than default?

@sdetweil
Copy link
Contributor Author

sdetweil commented May 6, 2023

well, you have characteristics too, so there is some setup someplace.. (i see begin())

so, I am advertising x, and then at some point I need to add your service too. so your code can work. (my app sends to a characteristic to turn on the OTA service)
I really want to add on the fly, if I can get nimble to work..
then add yours when I need the OTA service to execute, then remove yours when done

right now I am trying to
create my services (type 1, and type 2) and toggle between them, but nimble showing both.(remove doesn't), add says duplicate..., my ios app sees both services.. )

@vovagorodok vovagorodok self-assigned this May 7, 2023
@sdetweil
Copy link
Contributor Author

sdetweil commented May 8, 2023

so, I have this in platformio dev section

[env:esp32doit-devkit-v1-ota]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
build_flags = -DESP32
	-DUSE_ESP32_BLE_LIB
lib_deps = 
	arduino-libraries/Arduino_JSON@^0.2.0
	adafruit/Adafruit VL53L1X@^3.1.0
	https://github.com/vovagorodok/ArduinoBleOta
	jandrassy/ArduinoOTA@^1.0.9
	bakercp/CRC32@^2.0.0
	rlogiacco/CircularBuffer@^1.3.3

no nimble_arduino anywhere, it IS in the overall project libs from platformio's perspective, but not in this env

and I get this (to first error)

Processing esp32doit-devkit-v1-ota (platform: espressif32; board: esp32doit-devkit-v1; framework: arduino)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32doit-devkit-v1.html
PLATFORM: Espressif 32 (6.1.0) > DOIT ESP32 DEVKIT V1
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES: 
 - framework-arduinoespressif32 @ 3.20007.0 (2.0.7) 
 - tool-esptoolpy @ 1.40500.0 (4.5.0) 
 - toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 42 compatible libraries
Scanning dependencies...
Dependency Graph
|-- Arduino_JSON @ 0.2.0
|-- Adafruit VL53L1X @ 3.1.0
|   |-- Wire @ 2.0.0
|-- ArduinoBleOta @ 1.0.0+sha.b2a0dec
|   |-- ArduinoOTA @ 1.0.9
|   |-- ArduinoBLE @ 1.3.4
|   |-- ESP32 BLE Arduino @ 2.0.0
|   |-- CRC32 @ 2.0.0
|   |-- CircularBuffer @ 1.3.3
|-- ArduinoOTA @ 1.0.9
|-- CRC32 @ 2.0.0
|-- CircularBuffer @ 1.3.3
|-- ArduinoBLE @ 1.3.4
|-- ESP32 BLE Arduino @ 2.0.0
|-- EEPROM @ 2.0.0
|-- NimBLE-Arduino @ 1.4.1
Building in release mode
Compiling .pio/build/esp32doit-devkit-v1-ota/lib86c/ArduinoBleOta/ArduinoBleOtaClass.cpp.o
Compiling .pio/build/esp32doit-devkit-v1-ota/lib86c/ArduinoBleOta/ArduinoBleOtaClassESP32Ble.cpp.o
Compiling .pio/build/esp32doit-devkit-v1-ota/lib86c/ArduinoBleOta/ArduinoBleOtaClassNimBle.cpp.o
Compiling .pio/build/esp32doit-devkit-v1-ota/lib86c/ArduinoBleOta/BleOtaUploader.cpp.o
In file included from .pio/libdeps/esp32doit-devkit-v1-ota/ArduinoBleOta/src/BleOtaSizes.h:2,
                 from .pio/libdeps/esp32doit-devkit-v1-ota/ArduinoBleOta/src/BleOtaUploader.h:2,
                 from .pio/libdeps/esp32doit-devkit-v1-ota/ArduinoBleOta/src/BleOtaUploader.cpp:1:
.pio/libdeps/esp32doit-devkit-v1-ota/ArduinoBleOta/src/ArduinoBleOTA.h:5:17: note: #pragma message: esp32 defined
 #pragma message "esp32 defined"
                 ^~~~~~~~~~~~~~~
.pio/libdeps/esp32doit-devkit-v1-ota/ArduinoBleOta/src/ArduinoBleOTA.h:9:21: note: #pragma message: esp32 loading ESPBLE.h
     #pragma message "esp32 loading ESPBLE.h"
                     ^~~~~~~~~~~~~~~~~~~~~~~~
Compiling .pio/build/esp32doit-devkit-v1-ota/libd67/NimBLE-Arduino/nimble/nimble/controller/src/ble_ll_dtm.c.o
Compiling .pio/build/esp32doit-devkit-v1-ota/libd67/NimBLE-Arduino/nimble/nimble/controller/src/ble_ll_hci.c.o

I added #pragma to make sure I knew what path was being taken

why is NimBLE-Arduino there?

AFTER the build (pio run -e ....)
Nimble_arduino is back in the libs for this dev element?

here is my complete platformio.ini

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:nano_33_iot]
platform = atmelsam
board = nano_33_iot
framework = arduino
build_flags = -D __SAMD21__
lib_deps = 
	arduino-libraries/Arduino_JSON@^0.2.0
	adafruit/Adafruit VL53L1X@^3.1.0
	arduino-libraries/ArduinoBLE@^1.3.4
	cmaglie/FlashStorage@^1.0.0

[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
build_flags = -D ESP32
lib_deps = 
	arduino-libraries/Arduino_JSON@^0.2.0
	adafruit/Adafruit VL53L1X@^3.1.0

[env:esp32doit-devkit-v1-nimble]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
build_flags = -D ESP32 -D USE_NIMBLE
lib_deps = 
	arduino-libraries/Arduino_JSON@^0.2.0
	adafruit/Adafruit VL53L1X@^3.1.0
	h2zero/NimBLE-Arduino

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
build_flags = -D ESP32
lib_deps = 
	arduino-libraries/Arduino_JSON@^0.2.0
	adafruit/Adafruit VL53L1X@^3.1.0

[env:esp32doit-devkit-v1-ota]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
build_flags = -DESP32
	-DUSE_ESP32_BLE_LIB
lib_deps = 
	arduino-libraries/Arduino_JSON@^0.2.0
	adafruit/Adafruit VL53L1X@^3.1.0
	https://github.com/vovagorodok/ArduinoBleOta
	jandrassy/ArduinoOTA@^1.0.9
	bakercp/CRC32@^2.0.0
	rlogiacco/CircularBuffer@^1.3.3

my code builds correctly for all but the last entry (which is what I am trying to fix/add to my code for ESP32, without nimble til they fix the lib)

@sdetweil
Copy link
Contributor Author

sdetweil commented May 8, 2023

ok it compiles all the files whether needed or not.. SO the ifdef/endif block around the whole file..
so I compiled and build now.. SO.. i'll close this for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants