El ESP32 DevKit V2 dispone de conexión WiFi y BLE.
BLE o Bluetooth Low Energy es adecuada para conectar dos dispositivos cercanos y para transmitir poco volumen de datos, de manera no continua. Para transmitir de manera continua es más adecuado el bluetooth tradicional. La ventaja del BLE es que tiene un consumo mucho más bajo, por lo que lo hace especialmente útil en dispositivos IoT. Solo como orientación, en pico de gasto un BLE consume un 50% y en reposo un 1%, respecto al consumo del bluetooth tradicional. Eso implica que la duración puede extenderse de unos pocos días (tradicional) a años (BLE).
Para comenzar a familiarizarnos con el BLE del ESP32 vamos a utilizar el ejemplo ya disponible en Arduino IDE tras instalar la librería para la placa ESP32.
Pero antes de arrancar vamos a revisar dos conceptos clave en BLE.
I- Cliente y servidor
El primero es la diferencia entre cliente y servidor. El ESP32 puede funcionar como ambos (según se configure). El servidor anuncia su presencia para que otros dispositivos con receptor bluetooth (cliente) puedan identificarlo. Una vez que ha identificado el dispositvo con el que quiere vincularse, establece la conexión y comienza a recibir datos de entrada. Es lo que se denomina comunicación punto a punto. Hay otros tipos de comunicaciones más modernas en modo de emisor (un emisor, múltiples clientes) y en modo red de malla (múltiples emisores y múltiples clientes, interconectados). Nos centraremos en la primera y más sencilla: punto a punto.

II- ESTRUCTURA PROTOCOLO BLE
El segundo concepto previo a revisar es la estructura del protocolo de envío de datos por BLE.
El nivel más alto de la jerarquía es el Perfil, el segundo es el Servicio, el tercero son las Características y por último son las Propiedades-Valores-Descriptores.
1. Perfil. El nivel más alto de la jerarquía. Puede contener uno o más servicios.
2. Servicio. Una colección de información que puede, o no, centrarse en la información proveniente de un solo sensor. Si tuviéramos varios sensores conectados, tendríamos tantos servicios como sensores. Se han definido categorías para distintos tipos de datos (presión arterial, IMC, composición corporal, etc…).
3. Características. Es el tercer nivel jerárquico, y donde se sitúan los datos reales, la información sobre los datos (metadata) y a veces una descripción de los mismos. Es lo definido en el siguiente punto.
4. Propiedades-Valores-Descriptores.

Como veremos luego en la aplicación del móvil (nfRConnect o BlueLight), cada servicio, característica y descriptor, posee un código de identificación denominado UUID (ID Universal Único). Ese código puede ser asignado automáticamente o mediante un generador web.
III- ARRANQUE EMISOR
Acudimos a Archivo-Ejemplos-ESP32 BLE Arduino – BLE_server.

El código base del ejemplo BLE_server es:
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
Ported to Arduino ESP32 by Evandro Copercini
updates by chegewara
*/
#include
#include
#include
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
BLEDevice::init("Long name works now");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setValue("Hello World says Neil");
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();
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
}
Vamos a hacer dos pequeñas modificaciones al código:
1. Vamos a cambiar el nombre del dispositivo tal y como se envía por bluetooth (comunicación):
Donde pone:
BLEDevice::init(«Long name works now»);
Vamos a poner:
BLEDevice::init(«ESP32 ML Salud»);
2. Vamos a cambiar el contenido del mensaje que enviamos.
Donde pone:
pCharacteristic->setValue(«Hello World says Neil»);
Vamos a poner:
pCharacteristic->setValue(«Saludos desde la Universidad Europea»);
Y compilamos y subimos el programa a la ESP32 (no olvides apretar el botón de BOOT en la placa al hacer la subida).

En este momento, nuestra ESP32 ya está preparado para emitir mensajes BLE como servidor.

NOTA: Si el nombre que das al servidor es demasiado largo (en mi caso puse «ESP32 Machine Learning Salud»:
BLEDevice::init(«ESP32 Machine Learning Salud»)
El IDE de Arduino te da un error de:
«Stack smashing protect failure!
Backtrace…
Rebooting…»

En mi caso, se ha resuelto reduciendo el número de caracteres del nombre que le damos al dispositivo (de 28 a 14 caracteres).
IV- ARRANQUE DEL RECEPTOR O CLIENTE.
En nuestro teléfono móvil (en mi caso un iPhone XS) vamos a instalar nRFConnect, un programa para testear y desarrollar BLE e IoT en general.
Al abrir el programa, vemos esto.

Le damos a conectar para activar el escáner y vemos un listado de señales de bluetooth y de dispositivos que las emiten. Veréis que aparece nuestro dispositivo como «ESP32 ML Salud». Le damos a conectar y vemos:

Aquí podemos ver el código UUID que hemos adjudicado en nuestro código al Servicio («4FAFC201…»).
Si seleccionamos el último paquete, vemos:

Donde se especifica el código UUID de nuestra Característica con el valor: «Ox53-61-6C-75-64-6F-73-20-64-65-73-64-65-20-56-69-6C-6C-61» que es el texto que hemos escrito en el código de Arduino y que hemos subido compilado a la placa, con la salvedad de que está en código hexadecimal. Si lo traducimos con un traductor web cualquiera:

Obtenemos el texto que habíamos escrito:
«Saludos desde Villa».
No hemos conseguido que en un iPhone nRFConnect nos dé la información en texto ASCII/UTF-8. La aplicación para Android sí que lo hace. No olvidemos que lo importante es que el destino fina de esa información pueda gestionar adecuadamente nuestra información. Así que a efecto prácticos, nRFConnect hace lo que tiene que hacer. Si alguno quiere corregir eso utilizando un iPhone, puede usar otra aplicación que funciona excelentemente bien: LightBlue. Pantallazos sin más explicaciones (hacer click según la flecha):




Fuentes de información:
La mayor parte de la información de este artículo ha sido extraído del Random Nerd Tutorial: «Getting Started with ESP32 Bluetooth Low Energy (BLE) on Arduino IDE». Gracias a los autores (unos cracks).
https://randomnerdtutorials.com/esp32-bluetooth-low-energy-ble-arduino-ide/