ESP32 (Sparkfun ESP32 Thing), Arduino IDE, BLE connections
Posted: Sun Feb 27, 2022 8:35 pm
Hello,
I'm using a Sparkfun ESP32 Thing with the Arduino framework, trying to connect to and read from services on some W4 beacons - https://www.mokosmart.com/positioning-beacon-w3-w4/
I can successfully scan for the beacons, get the address, local name etc. however, actually connecting never succeeds - the call to client->connect() never returns.
My sketch is:
And here's some sample output from the listFoundSensorDetails function:
There is a delay between 'uint32_t rc = m_semaphoreOpenEvt.wait('connect');' and 'getCattcIf' of around 30-60 seconds. The 1...8 debug lines are simply stage markers showing how far through the code I've got.
You might be wondering where all that debug information comes from. It's from BLEClient - I added some printf statements to help me understand what's going on. Apart from debug output, the only thing I've changed is to add a timeout in the 'take' calls. e.g.:
Now it looks to me like it's getting into the getServices function and eventually waiting for the ESP_GATTC_OPEN_EVT, but that never arrives. ESP_GATTC_DISCONNECT_EVT does though, which we can see in the debug output.
The beacons do work - I can connect with the nRFConnect app and see the data. I can also connect with the MokoBeacon app on my iPad - the beacons are from Moko.
So, any suggestions as to what I can do to get these beacons to connect to my Sparkfun ESP32 Thing?
Thanks for any suggestions.
Ian
I'm using a Sparkfun ESP32 Thing with the Arduino framework, trying to connect to and read from services on some W4 beacons - https://www.mokosmart.com/positioning-beacon-w3-w4/
I can successfully scan for the beacons, get the address, local name etc. however, actually connecting never succeeds - the call to client->connect() never returns.
My sketch is:
Code: Select all
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEClient.h>
#include <BLEUtils.h>
#include <BLEDevice.h>
#include <BLEAdvertisedDevice.h>
#include <sstream>
BLEScan* pBLEScan;
int sensorCount = 0;
int scanTime = 2;
BLEAdvertisedDevice sensorsFound[10];
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks
{
void onResult(BLEAdvertisedDevice advertisedDevice)
{
std::stringstream ss;
if (advertisedDevice.haveManufacturerData())
{
int dataLength = advertisedDevice.getManufacturerData().length();
char *pHex = BLEUtils::buildHexData(nullptr, (uint8_t*)advertisedDevice.getManufacturerData().data(), dataLength);
ss << pHex;
free(pHex);
if (isMyBeacon(ss.str().c_str(), 0))
{
Serial.printf("Beacon: %s \n", ss.str().c_str());
sensorsFound[sensorCount] = advertisedDevice;
sensorCount++;
Serial.printf("\n\n");
}
}
}
bool isMyBeacon(const char* beaconManufacturer, int offset)
{
const char* _beaconManufacturerUUID = "4c000215e2c56db5dffb48d2b060d0f5a71096e";
bool matches = true;
for (int i = 0; i < 39; i++)
{
if (_beaconManufacturerUUID[i] != beaconManufacturer[i + offset])
{
matches = false;
break;
}
}
return matches;
}
};
int getMinorVersion(uint8_t *pData, int dataLen)
{
int version = getVersion(pData, dataLen, 3);
return version;
}
int getMajorVersion(uint8_t *pData, int dataLen)
{
int version = getVersion(pData, dataLen, 5);
return version;
}
int getVersion(uint8_t *pData, int dataLen, int offset)
{
int versionOffset = dataLen - offset;
byte lowByte = (uint8_t)pData[versionOffset + 1];
byte highByte = (uint8_t)pData[versionOffset];
int version = highByte << 8 | lowByte;
return version;
}
void listFoundSensorDetails(BLEAdvertisedDevice *advertisedDevice)
{
BLEScan *scan = advertisedDevice->getScan();
std::string serviceData = advertisedDevice->getServiceData();
int dataLength = advertisedDevice->getManufacturerData().length();
Serial.println("Details: "); Serial.println(advertisedDevice->toString().c_str());
Serial.print("Address: "); Serial.println(advertisedDevice->getAddress().toString().c_str());
int minor = getMinorVersion((uint8_t*)advertisedDevice->getManufacturerData().data(), dataLength);
int major = getMajorVersion((uint8_t*)advertisedDevice->getManufacturerData().data(), dataLength);
Serial.printf("Sensor ID %d:%03d\n", major, minor);
Serial.print("Name"); Serial.println(advertisedDevice->getName().c_str());
if (advertisedDevice->haveServiceUUID())
{
Serial.print("Service UUID:"); Serial.println(advertisedDevice->getServiceUUID().toString().c_str());
}
else
{
Serial.println("haveServiceUUID was false.");
}
if (advertisedDevice->haveServiceData())
{
Serial.print("Service Data UUID:"); Serial.println(advertisedDevice->getServiceDataUUID().toString().c_str());
Serial.print("Service Data:"); Serial.println(advertisedDevice->getServiceData().c_str());
}
else
{
Serial.println("haveServiceData was false.");
}
size_t payloadLength = advertisedDevice->getPayloadLength();
Serial.print("Payload length "); Serial.println(payloadLength);
listServices(advertisedDevice);
}
void listServices(BLEAdvertisedDevice *advertisedDevice)
{
static BLEUUID serviceUUID("180F-0000-1000-8000-00805F9B34FB");
static BLEUUID charUUID("2A19-0000-1000-8000-00805F9B34FB");
printf("listServices\n");
Serial.println("creat BLEClient");
BLEAddress pAddress = advertisedDevice->getAddress();
Serial.print("Address: "); Serial.println(pAddress.toString().c_str());
BLEClient *pClient = BLEDevice::createClient();
Serial.println("created the client");
pClient->connect(pAddress);
printf("back from connect\n");
BLERemoteService *pRemoteService = pClient->getService(serviceUUID);
printf("back from getService\n");
int serviceCount = advertisedDevice->getServiceCount();
Serial.printf(" %d services exposed\n", serviceCount);
if (serviceCount > 0)
{
for (int i = 0; i < serviceCount; i++)
{
BLEUUID uuid = advertisedDevice->getAllServiceUUIDs()[i];
Serial.printf(" UUID: %s \n", uuid.toString());
}
}
pClient->disconnect();
}
void listAllFoundSensorDetails()
{
if (sensorCount == 0)
{
printf("No sensors found\n");
}
else
{
for (int i = 0; i < sensorCount; i++)
{
listFoundSensorDetails(&sensorsFound[i]);
Serial.println("\n\n\n\n");
}
}
Serial.println("**********************************************");
}
void setup()
{
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->start(scanTime, false);
}
void loop()
{
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
Serial.println(foundDevices.getCount());
Serial.println("Scan done!");
pBLEScan->clearResults();
pBLEScan->stop();
listAllFoundSensorDetails();
sensorCount = 0;
delay(20);
}
Code: Select all
Details:
Name: S00383, Address: e1:4e:ab:f2:64:dd, manufacturer data: 4c000215e2c56db5dffb48d2b060d0f5a71096e00000017fbf, txPower: -12
Address: e1:4e:ab:f2:64:dd
Sensor ID 0:383
NameS00383
haveServiceUUID was false.
Service Data UUID:0000ff01-0000-1000-8000-00805f9b34fb
Service Data:R
Payload length 58
listServices
creat BLEClient
Address: e1:4e:ab:f2:64:dd
created the client
1
do m_semaphoreRegEvt.take('connect');
done m_semaphoreRegEvt.take('connect');
2
4
do m_semaphoreRegEvt.wait('connect');
getGattcIf
getGattcIf
into gattClientEventHandler
do m_semaphoreRegEvt.give();
done m_semaphoreRegEvt.give();
done m_semaphoreRegEvt.wait('connect');
5
m_semaphoreOpenEvt.take(msTimeOut,'connect'
m_semaphoreOpenEvt.take(msTimeOut,'connect'
6
getPeerAddress
7
8
uint32_t rc = m_semaphoreOpenEvt.wait('connect');
getGattcIf
into gattClientEventHandler
ESP_GATTC_DISCONNECT_EVT
m_semaphoreRssiCmplEvt.give();
done m_semaphoreRssiCmplEvt.give();
m_semaphoreSearchCmplEvt.give(1);
done m_semaphoreSearchCmplEvt.give(1);
You might be wondering where all that debug information comes from. It's from BLEClient - I added some printf statements to help me understand what's going on. Apart from debug output, the only thing I've changed is to add a timeout in the 'take' calls. e.g.:
Code: Select all
printf("m_semaphoreRssiCmplEvt.take(msTimeOut, 'getRssi');\n");
m_semaphoreRssiCmplEvt.take(msTimeOut, "getRssi");
printf("done m_semaphoreRssiCmplEvt.take(msTimeOut, 'getRssi');\n");
The beacons do work - I can connect with the nRFConnect app and see the data. I can also connect with the MokoBeacon app on my iPad - the beacons are from Moko.
So, any suggestions as to what I can do to get these beacons to connect to my Sparkfun ESP32 Thing?
Thanks for any suggestions.
Ian