ESP32_LoRaWAN-master + BLE libraries conflict

I am trying to use both the LoRaWAN (using the library in https://github.com/HelTecAutomation/ESP32_LoRaWAN, based on the OTAA_OLED example ) and the BLE (using the library “ESP32 BLE for Arduino 1.0.1” included in the Heltec-esp32 package, based on the BLE_UART example) in the Wireless Stick. I use the Arduino IDE.

Both of them libraries work correcly on their own, but when I try to use both in the same sketch I get the following error:

Arduino:1.8.10 (Windows 10), Tarjeta:“Wireless Stick, Disabled, default_8MB, 240MHz (WiFi/BT), QIO, 80MHz, 8MB (64Mb), 921600, None”

In file included from C:\Users\shernando\Documents\Arduino\libraries\ESP32_LoRaWAN-master\src/board.h:35:0,

             from C:\Sergio\Arduino\ESP32_LoRaWAN\examples\LoRaWAN_Bluetooth\LoRaWAN_Bluetooth.ino:4:

C:\Users\shernando\Documents\Arduino\libraries\ESP32_LoRaWAN-master\src/sx1276.h:469:13: warning: ‘void RxChainCalibration()’ declared ‘static’ but never defined [-Wunused-function]

static void RxChainCalibration( void );

         ^

C:\Users\shernando\AppData\Local\Arduino15\packages\Heltec-esp32\hardware\esp32\0.0.4/tools/sdk/lib\libbt.a(aes.o): In function `aes_set_key’:

/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/bt/bluedroid/stack/smp/aes.c:514: multiple definition of `aes_set_key’

libraries\ESP32_LoRaWAN-master\aes.c.o:C:\Users\shernando\Documents\Arduino\libraries\ESP32_LoRaWAN-master\src/aes.c:514: first defined here

C:\Users\shernando\AppData\Local\Arduino15\packages\Heltec-esp32\hardware\esp32\0.0.4/tools/sdk/lib\libbt.a(aes.o): In function `aes_cbc_encrypt’:

aes.c:(.text.aes_cbc_encrypt+0x0): multiple definition of `aes_cbc_encrypt’

libraries\ESP32_LoRaWAN-master\aes.c.o:aes.c:(.text.aes_cbc_encrypt+0x0): first defined here

collect2.exe: error: ld returned 1 exit status

Se encontraron varias bibliotecas para “BLEDevice.h”
Usado: C:\Users\shernando\AppData\Local\Arduino15\packages\Heltec-esp32\hardware\esp32\0.0.4\libraries\BLE
Se encontraron varias bibliotecas para “aes.h”
Usado: C:\Users\shernando\Documents\Arduino\libraries\ESP32_LoRaWAN-master
Se encontraron varias bibliotecas para “SPI.h”
Usado: C:\Users\shernando\AppData\Local\Arduino15\packages\Heltec-esp32\hardware\esp32\0.0.4\libraries\SPI
Se encontraron varias bibliotecas para “Wire.h”
Usado: C:\Users\shernando\AppData\Local\Arduino15\packages\Heltec-esp32\hardware\esp32\0.0.4\libraries\Wire
exit status 1
Error compilando para la tarjeta Wireless Stick.

Does anybody know what I am doing wrong?

Can you upload your code here?

The code I am trying is the following:

#include <Arduino.h>

#include <aes.h>
#include <board.h>
#include <cmac.h>
#include <Commissioning.h>
#include <delay.h>
#include <dht11.h>
#include <fifo.h>
#include <LoRa.h>
#include <LoRaMac-definitions.h>
#include <LoRaMac.h>
#include <LoRaMacCrypto.h>
#include <LoRaMacTest.h>
#include <Mcu.h>
#include <OLEDDisplay.h>
#include <OLEDDisplayFonts.h>
#include <OLEDDisplayUi.h>
#include <pinName-board.h>
#include <pinName-ioe.h>
#include <radio.h>
#include <rtc-board.h>
#include <RTE_Components.h>
#include <SSD1306.h>
#include <SSD1306Wire.h>
#include <sx1276-board.h>
#include <sx1276.h>
#include <sx1276Regs-Fsk.h>
#include <sx1276Regs-LoRa.h>
#include <timer.h>
#include <utilities.h>

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <BLE2902.h>

/*
BASADO EN:
HelTec Automation™ LoRaWAN 1.0.2 OTAA example use OTAA, CLASS A

   - Only ESP32 + LoRa series boards can use this library, need a license
     to make the code run(check you license here: http://www.heltec.cn/search/);

You can change some definition in “Commissioning.h” and “LoRaMac-definitions.h”

BLE:
The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with “WRITE”
Has a characteristic of: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E - used to send data with “NOTIFY”

The design of creating the BLE server is:

  1. Create a BLE Server
  2. Create a BLE Service
  3. Create a BLE Characteristic on the Service
  4. Create a BLE Descriptor on the characteristic
  5. Start the service.
  6. Start advertising.

In this example rxValue is the data received (only accessible inside that function).
And txValue is the data to be sent, in this example just a byte incremented every second.
*/

#define V2
#define CLASS CLASS_A

#define BOTON 0

#ifdef V2 //WIFI Kit series V1 not support Vext control
#define DIO1 35 // GPIO35 – SX127x’s IRQ(Interrupt Request) V2
#else
#define DIO1 33 // GPIO33 – SX127x’s IRQ(Interrupt Request) V1
#endif

#define Vext 21

#if defined Wireless_Stick
#define DISPLAY_FUENTE DejaVu_Sans_Mono_8 //DialogInput_plain_8
#define DISPLAY_GEOMETRY GEOMETRY_64_32
#define DIPLAY_H_CENTER 32
#define DISPLAY_V_CENTER (16-4)
#define DIPLAY_LINEA_0 0
#define DIPLAY_LINEA_1 10
#define DIPLAY_LINEA_2 20
#else
#define DISPLAY_FUENTE ArialMT_Plain_16
#define DISPLAY_GEOMETRY GEOMETRY_128_64
#define DIPLAY_H_CENTER 64
#define DISPLAY_V_CENTER (32-8)
#define DIPLAY_LINEA_0 10
#define DIPLAY_LINEA_1 30
#define DIPLAY_LINEA_2 48
#endif

#define SERVICE_UUID “6E400001-B5A3-F393-E0A9-E50E24DCCA9E” // UART service UUID
#define CHARACTERISTIC_UUID_RX “6E400002-B5A3-F393-E0A9-E50E24DCCA9E”
#define CHARACTERISTIC_UUID_TX “6E400003-B5A3-F393-E0A9-E50E24DCCA9E”

bool OVER_THE_AIR_ACTIVATION = true;

uint8_t DevEui[] = { 0x22,0x32,0x33, 0x00, 0x00, 0x88, 0x88, 0x33 };
uint8_t AppEui[] = { 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x04 };
uint8_t AppKey[] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x66, 0x01 };

//LICENSE
uint32_t LICENSE[4] = {0x5A78D2C3, 0x2691AD3D, 0x9DECB5B4, 0x7E0BCFF8}; //470v2

//ABP
uint32_t ABP_DevAddr = ( uint32_t )0x26011713 ;
RTC_DATA_ATTR uint8_t ABP_NwkSKey[] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x66, 0x02 };
RTC_DATA_ATTR uint8_t ABP_AppSKey[] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x66, 0x01 };

SSD1306 display(0x3c, SDA, SCL, RST_LED, DISPLAY_GEOMETRY);

BLECharacteristic *pCharacteristic;
BLEServer *pServer;
bool deviceConnected = false;
bool oldDeviceConnected = false;
bool BTRxData = false;
std::string BTRxStringValue;

float txValue = 0;
const int readPin = 32; // Use GPIO number. See ESP32 board pinouts

extern McpsIndication_t McpsIndication;

//Delivery of data on port 2
void app(uint8_t data)
{
lora_printf(“data:%d\r\n”, data);
}

/*
BLUETOOTH CALLBACKS
/
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer
pServer) {
deviceConnected = true;
};

void onDisconnect(BLEServer* pServer) {
  deviceConnected = false;
}

};

class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
//std::string rxValue = pCharacteristic->getValue();
BTRxStringValue = pCharacteristic->getValue();
//BTRxValue = pCharacteristic->getData();
BTRxData = true;
}
};

void BTRespuestaACK()
{
char txString[] = {“ACK”};
pCharacteristic->setValue(txString);
pCharacteristic->notify(); // Send the value to the app!
lora_printf(“Bluetooth - ACK\n”);
}

void BTRespuestaNACK()
{
char txString[] = {“NACK”};
pCharacteristic->setValue(txString);
pCharacteristic->notify(); // Send the value to the app!
lora_printf(“Bluetooth - NACK!!!\n”);
}

void BTSendJoinOK()
{
char txString[] = {“Joined”};
pCharacteristic->setValue(txString);
pCharacteristic->notify(); // Send the value to the app!
lora_printf(“Bluetooth - Joined\n”);
}

void BTSendJoinError()
{
char txString[] = {“Join ERROR”};
pCharacteristic->setValue(txString);
pCharacteristic->notify(); // Send the value to the app!
lora_printf(“Bluetooth - Join Error\n”);
}

void BTSendACK()
{
char txString[] = {“Frame ACKED”};
pCharacteristic->setValue(txString);
pCharacteristic->notify(); // Send the value to the app!
lora_printf(“Bluetooth - Frame ACKED\n”);
}

void BTSendNoACK()
{
char txString[] = {“Frame NOT ACKED”};
pCharacteristic->setValue(txString);
pCharacteristic->notify(); // Send the value to the app!
lora_printf(“Bluetooth - Frame NOT ACKED\n”);
}

/*
/
pTxCharacteristic->setValue(&txValue, 1);
pTxCharacteristic->notify();
txValue++;
*/

/*
NOTIFICACIONES LORAWAN
*/

void LEDdisplayJOINING()
{
digitalWrite(Vext, LOW);
delay(50);
display.wakeup();
display.clear();
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(DIPLAY_H_CENTER, DISPLAY_V_CENTER, “JOINING…”);
display.display();
}
void LEDdisplayJOINED()
{
digitalWrite(Vext, LOW);
delay(50);
display.wakeup();
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.clear();
display.drawString(DIPLAY_H_CENTER, DISPLAY_V_CENTER, “JOINED”);
display.display();
delay(2000);
display.sleep();
digitalWrite(Vext, HIGH);
}
void LEDdisplayJOINERROR()
{
digitalWrite(Vext, LOW);
delay(50);
display.wakeup();
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.clear();
display.drawString(DIPLAY_H_CENTER, DISPLAY_V_CENTER, “JOIN ERROR”);
display.display();
delay(2000);
display.sleep();
digitalWrite(Vext, HIGH);
}

void LEDdisplaySENDING()
{
digitalWrite(Vext, LOW);
delay(10);
display.wakeup();
display.init();
delay(50);
display.flipScreenVertically();
display.clear();
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.setFont(DISPLAY_FUENTE);
display.drawString(DIPLAY_H_CENTER, DISPLAY_V_CENTER, “SENDING…”);
display.display();
}
void LEDdisplayACKED()
{
display.clear();
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(DIPLAY_H_CENTER, DIPLAY_LINEA_0, “ACK RECEIVED”);
display.drawString(DIPLAY_H_CENTER, DIPLAY_LINEA_1, "rssi= " + String(McpsIndication.Rssi) + “dBm”);
display.drawString(DIPLAY_H_CENTER, DIPLAY_LINEA_2, “DR=” + String(McpsIndication.RxDatarate));
display.display();
if (CLASS == CLASS_A)
{
delay(5000);
display.sleep();
digitalWrite(Vext, HIGH);
}
}

void LEDdisplayNOACK()
{
display.setTextAlignment(TEXT_ALIGN_CENTER);
#if defined Wireless_Stick
display.drawString(DIPLAY_H_CENTER, DIPLAY_LINEA_1, “NO ACK RECEIVED”);
#else
display.clear();
display.drawString(DIPLAY_H_CENTER, DISPLAY_V_CENTER, “NO ACK RECEIVED”);
#endif
display.display();
}

/*
DISPLAY
*/
void LEDdisplaySTART()
{
display.wakeup();
display.init();
delay(100);
display.flipScreenVertically();
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.clear();
display.setFont(DISPLAY_FUENTE);
display.drawString(DIPLAY_H_CENTER, DIPLAY_LINEA_0, “STARTING”);
display.drawString(DIPLAY_H_CENTER, DIPLAY_LINEA_1, “LORAWAN”);
display.display();
}

/*
SETUP
*/
void setup()
{
pinMode(Vext, OUTPUT);
digitalWrite(Vext, LOW); // OLED USE Vext as power supply, must turn ON Vext before OLED init

pinMode(BOTON, INPUT_PULLUP);
pinMode(LED, OUTPUT);

Serial.begin(115200);
while (!Serial);
delay(100);

// DISPLAY
LEDdisplaySTART();

// LORA
SPI.begin(SCK, MISO, MOSI, SS);
Mcu.begin(SS, RST_SX127x, DIO0, DIO1, LICENSE);
DeviceState = DEVICE_STATE_INIT;
LoRa.DeviceStateInit(CLASS);

// BLUETOOTH
// Create the BLE Device
BLEDevice::init(“LoRaWAN Test”); // Give it a name
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);

//pCharacteristic->addDescriptor(new BLE2902());

BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);

pCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
pServer->getAdvertising()->start();
Serial.println(“Bluetooth - Waiting a client connection to notify…”);

State = STATE_INIT;

}

bool JoinAttempt = false;
bool SendAttempt = false;
bool PararLoRa = false;

void loop()
{

// BLUETOOTH
if (deviceConnected) {
if (BTRxData)
{
switch (BTRxStringValue[0])
{
case ‘J’:
{
if ((DeviceState != DEVICE_STATE_INIT) || (IsLoRaMacNetworkJoined == true))
BTRespuestaNACK();
else
{
DeviceState = DEVICE_STATE_JOIN;
BTRespuestaACK();
}
break;
}
case ‘S’:
{
if ((DeviceState != DEVICE_STATE_INIT) || (IsLoRaMacNetworkJoined == false))
BTRespuestaNACK();
else
{
DeviceState = DEVICE_STATE_SEND;
BTRespuestaACK();
}
break;
}
}
BTRxData = 0;
}
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
lora_printf(“Bluetooth - Desconectado\n”);
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
lora_printf(“Bluetooth - start advertising”);
oldDeviceConnected = deviceConnected;
PararLoRa = true;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
lora_printf(“Bluetooth - Conectado\n”);
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}

// LORAWAN

switch ( DeviceState )
{
case DEVICE_STATE_INIT: // Espera a que desde el bluetooth se cambie de estado
{
if (PararLoRa)
{
LoRa.DeviceStateInit(CLASS);
PararLoRa = false;
}

    break;
  }
case DEVICE_STATE_JOIN:
  {
    if (JoinAttempt == true)                          // Error en el intento de join
    {
      LEDdisplayJOINERROR();
      BTSendJoinError();
      DeviceState = DEVICE_STATE_INIT;
      JoinAttempt = false;
    }
    else
    {
      JoinAttempt = true;
      LoRa.DeviceStateInit(CLASS);
      LEDdisplayJOINING();
      LoRa.DeviceStateJion(OVER_THE_AIR_ACTIVATION);  // Si hace el join correcto, acaba con estado DEVICE_STATE_SEND. Si falla, vuelve con estado DEVICE_STATE_JOIN
    }
    break;
  }
case DEVICE_STATE_SEND:
  {
    if (JoinAttempt == true)                // Intentando join
    { // Join correcto
      if (isJioned == 1)
      {
        isJioned--;
        LEDdisplayJOINED();
        BTSendJoinOK();
      }
      JoinAttempt = false;
      DeviceState = DEVICE_STATE_INIT;
    }
    else if (SendAttempt == true)           // Se ha enviado trama: si vuelve a este estado es que no ha habido respuesta
    {
      LEDdisplayNOACK();
      SendAttempt = false;
      BTSendNoACK();
      DeviceState = DEVICE_STATE_INIT;
    }
    else                                    // Enviar la trama recibida del Bluetooth
    {
      LEDdisplaySENDING();
      lora_printf("Into send state\n");
      // void PrepareMsgFrame( uint8_t port, uint8_t Msg2Send[], uint8_t length )          
      PrepareMsgFrame( BTRxStringValue[1],(uint8_t *) &BTRxStringValue[2] , BTRxStringValue.length()-2);
      LoRa.DeviceStateSend();
      DeviceState = DEVICE_STATE_CYCLE;
    }
    break;
  }
case DEVICE_STATE_CYCLE:
  {
    // Schedule next packet transmission
    //TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime );
    TimerSetValue( &TxNextPacketTimer, 5000 );                      // Al acabar el tiempo se despierta con estado DEVICE_STATE_SEND o DEVICE_STATE_JOIN
    TimerStart( &TxNextPacketTimer );
    DeviceState = DEVICE_STATE_SLEEP;
    break;
  }
case DEVICE_STATE_SLEEP:
  {
    if (isAckReceived == 1)
    {
      SendAttempt=false;
      isAckReceived--;
      LEDdisplayACKED();
      BTSendACK();

      lora_printf("DownLink msg : %s\n", msgRx.isDwn ? "true" : "false");    // debug
      if ( msgRx.isDwn == true ) // something received
      {
        lora_printf("Msg received: %s\n", msgRx.msg);
      }
      DeviceState = DEVICE_STATE_INIT;
    }
    LoRa.DeviceSleep(CLASS, DebugLevel);
    break;
  }
default:
  {
    DeviceState = DEVICE_STATE_INIT;
    break;
  }

}

}

I solved it. I just changed the name of those 2 conflicting functions (aes_set_key and aes_cbc_encrypt) in the ESP32_LoRaWAN-master library and it compiles now.

Ok, next problem now. BLE does not work in sleep and the LoRaWAN library does not seem to work without the call to “LoRa.DeviceSleep” in the DEVICE_STATE_SLEEP state…
Any suggestions?

Maybe there is no better way, you need BLE keep connection during low power status?

The fact is that I do, as the LoRaWAN communication is triggered by a command received by BLE, so I need to send the confirmation back to BLE.
As the LoRaWAN library activates low power during the wait for the reception windows, the BLE gets disconnected, and I do not receive the onDisconnect callback until much later, so I try to send the LoRaWAN answer to the BLE before knowing it has already been disconnected due to the low power…