Connecting on ESP32
Opened this issue · 15 comments
Hi there. Love this library!!
Just trying to get it to work with ESP32. No luck connecting to advertised service UUID.
On my phone using the BLE Scanner app, I can see and connect to my service. But don't see the service listed from browser using myBLE.connect(serviceUuid, gotCharacteristics). Just hangs and says "no compatible devices found."
The code for ESP32 is quite different from your sample code for Arduino, but at the end of the day, it advertises a serviceUUID and that's confirmed working... so don't think there's too much to go wrong.
Bug? Or am I doing something wrong? Does it need something else in that ArduinoBLE.h library? (I'm not using that library). I'm using:
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
here's the esp32 code running on the device.
ble.esp32.txt
Was hoping it might be an SSL issue... but just set up Ngrok and hit it via https and no luck seeing the service with that approach either.
I do see it using the device using the code here:
https://googlechrome.github.io/samples/web-bluetooth/device-info.html?allDevices=true
Ok, figured it out.
Maybe the spec changed but in your connect
function on line 21, you're filtering by by "services" - which is not the same as a UUID. It's expecting the name of a service there like 'battery_service'...
Seems like you want to filter by name instead - and pass that in as a param as well. like:
connect(serviceUuid, serviceName, callback) {
const options = {
filters: [{
namePrefix: [serviceName],
}],
};
oh, interestingly, now that i've connected successfully, i can also connect successfully from your example at https://itpnyu.github.io/p5ble-website/docs/connect-disconnect (i used your same UUID). I wonder if this is why you may not have noticed that it wasn't working??... maybe it gets cached in some way... and then bypasses the filters?
Nope, scratch that - it only shows up on https://itpnyu.github.io/p5ble-website/docs/connect-disconnect if I'm currently paired with it using my modified connect script. If I disconnect there, it doesn't work again on your example site.
On further experimentation, the UUID still needs to be in the options as so:
connect(serviceUuid, serviceName, callback) {
const options = {
filters: [{
namePrefix: [serviceName],
}],
optionalServices: [serviceUuid]
};
Hi @bigrig2212, thank you for reporting the issue! I'd love to make it working with ESP32.
I think passing serviceUuid
as services
intofilters
should also work. In this Web Bluetooth example, it's checking if serviceUuid.startsWith('0x')
, then it will read it as an integer, and then pass it to filters:
navigator.bluetooth.requestDevice({filters: [{services: [serviceUuid]}]})
If on your phone in the BLE Scanner app, you can see and connect to your service, then p5 sketch should be able to find your device. When you are running the p5 sketch, you just need to change the serviceUuid here. What is your service uuid? Does it have same format like:
const serviceUuid = "e1132322-a39d-45be-8db0-16983b2a4fe3";
const serviceUuid = "19b10010-e8f2-537e-4f6c-d104768a1214";
Not sure if it applies or not, but one thing I had to do was add this to the ESP32 example:
// Create the BLE Service BLEService *pService = pServer->createService(SERVICE_UUID); pServer->getAdvertising()->addServiceUUID(SERVICE_UUID);
I've successfully been able to get p5.ble to read a characteristic using an ESP32. Here's the Arduino code:
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "19b10000-e8f2-537e-4f6c-d104768a1214"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value == "on"){
digitalWrite(LED_BUILTIN, HIGH);
}
else {
digitalWrite(LED_BUILTIN, LOW);
}
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
Serial.println("1- Download and install an BLE scanner app in your phone");
Serial.println("2- Scan for BLE devices in the app");
Serial.println("3- Connect to MyESP32");
Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
Serial.println("5- See the magic =)");
BLEDevice::init("MyESP32");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("water");
pService->start();
// BLEAdvertising *pAdvertising = pServer->getAdvertising(); // this still is working for backward compatibility
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
}
However, I cannot get p5.ble to successfully write to the same characteristic. The ESP32 triggers the callback but the value is empty (?). The serial monitor writes:
*********
New value: �
*********
I can connect to the ESP32 with an app like nRF Connect on my Android phone and successfully write a text string to the characteristic.
Any ideas welcome.
Hey,
I am having the same issue with ESP32 connection with chrome... have you found a solution? Can you provide a solution for the web app?
@FilippoCinotti , @mjvo the incoming information will be interpreted as ASCII. Try sending a number 65 and you should see a letter 'A'.
FWIW, I was only to successfully write bytes from p5.ble to an Adafruit Bluefruit LE SPI Friend. In order to write strings, I modified lines 104-106 of p5.ble.js (in the write function) as follows:
const bufferToSend = Uint8Array.of(inputValue);
console.log(`Writing ${inputValue} to Characteristic...`);
return characteristic.writeValue(bufferToSend);
to
let encoder = new TextEncoder('utf-8');
console.log(`Writing ${inputValue} to Characteristic...`);
characteristic.writeValueWithoutResponse(encoder.encode(inputValue));
Great lib!
The strange thing is it works on Android. It runs perfectly.
But once I do try it on PC (OS does not matter) it will not find the ESP32.
I have same issue. The p5.ble.js cannot find my ESP32 BLE device but other mobile apps like Bluefruit BLE Connect can find and connect without any issue.