Tutorial del Internet de las Cosas y Bluetooth con el ESP32
Juan Antonio Villalpando
Volver al índice del tutorial
____________________________
160.- Bluetooth Low Energy. BLE. Librería. De AI2 a ESP32. De ESP32 a AI2.
_________________________________
- BLE. Librería.
- El módulo Wemos D1 R32 con el chip ESP32, tiene Bluetooth: v4.2 BR/EDR y Bluetooth Low Energy (BLE), así que lo podemos utilizar con el Bluetooth clásico 4.0 y con el BLE.
- En esta página podemos encontrar una extensión para que App Inventor pueda trabajar con BLE:
- http://iot.appinventor.mit.edu/#/bluetoothle/bluetoothleintro
- Aquí muestro distintas versiones de esta extensión, en estos tutoriales vamos a utilizar la 2018-11-24
BLE-with-new-ConnectDevice.aix (2019-06-27) (Version beta) (mirror)
edu.mit.appinventor.ble-20181124.aix (20181124) (Version estable)
edu.mit.appinventor.ble.aix
(20171109)
edu.mit.appinventor.BluetoothLE.aix (version 2)
- http://ai2.appinventor.mit.edu/reference/other/IoT.html (Ejemplo. 2016)
- Por otra parte me voy a basar en los ejemplos que podemos consultar en esta dirección:
https://github.com/nkolban/ESP32_BLE_Arduino/tree/7951347ed68313d75c367e1f2cce763cb56d1eb2
- Lo primero que tendría que hacer es bajar y descomprimir este archivo: ESP32_BLE.zip
- (Otra versión: ESP32_BLE_2.zip)
- Obtendremos la carpeta ESP32_BLE, copiamos esa carpeta en la carpeta ../Arduino/libraries/
- Puedes encontrar ejemplos en su carpeta examples.
________________________________________________________________
- NOTA: en estos ejemplos que vamos a realizar debemos tener en cuenta que a veces el MIT COMPANION no actualiza el Bluetooth cuando hacemos cambios en el código, así que si no obtienes en el listado el BLE de la tarjeta Wemos, desconecta la app del MIT COMPANION y vuélvela a conectar.
- Otra cosa importante es que cada vez que hagamos cambios en los códigos Deshabilitemos y Habilitemos el Bluetooth del móvil, para eso he puesto la extensión com.KIO4_Bluetooth.aix en estos ejemplos.
com.KIO4_Bluetooth.aix
- Si sigue sin funcionarte estos ejemplos, instala la aplicación en vez de utilizar el emulador de MIT Companion.
- En los ejemplos de Notificaciones he puesto:
- El bloque de solicitud de permisos.
- En Android 5 me ha funcionado mejor que en Android 9. A veces para que funcionara en Android 9 lo ejecutaba antes en Android 5 y después en Android 9.
- Para que funcione BLE, el móvil debe tener activado el permiso de Ubicación (Location)
https://stackoverflow.com/questions/33045581/location-needs-to-be-enabled-for-bluetooth-low-energy-scanning-on-android-6-0
https://stackoverflow.com/questions/33043582/bluetooth-low-energy-startscan-on-android-6-0-does-not-find-devices/33045489#33045489
_________________________________
1.- Listado de BLE cercanos.
https://github.com/nkolban/ESP32_BLE_Arduino/tree/master/examples/BLE_scan
scan_ble.ino |
/*
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 <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
int scanTime = 30; //In seconds
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
}
};
void setup() {
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
BLEScan* pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
BLEScanResults foundDevices = pBLEScan->start(scanTime);
Serial.print("Devices found: ");
Serial.println(foundDevices.getCount());
Serial.println("Scan done!");
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
}
|
- BLE Scanner.
- Podemos ver los UUID con esta aplicación:
https://play.google.com/store/apps/details?id=com.macdom.ble.blescanner&hl=es
_________________________________
2.- App Inventor envía información a la tarjeta mediante BLE. Monitor Serie.
p110i_esp32_ble_enviar.aia
- App Inventor (Android) conecta por BLE con la tarjeta. Escribimos un mensaje y lo enviamos. La tarjeta tomará ese mensaje y lo presentará en el Monitor Serie.
- Este mensaje estará en las variables value y valor.
- Se presentará de varias forma, una mediante value y otra mediante el String valor en la parte del código de BLE.
- Además la variable valor se presentará cada 2 segundos mediante el bloque loop {}
- IMPORTANTE: aunque pongamos un texto largo, solo se enviará un paquete de 20 caracteres.
- El siguiente mensaje: "El Ñandú corrió por Cádiz" se mostrará en el Monitor Serie: "El Ñandú corrió p", observa 17 caracteres, eso es porque los caracteres especiales Ñ, ó, ú, se envían en dos bytes.
_________________________________
- Diseño.
_________________________________
- Bloques.
- Observa los números de serviceUuid y characteristicUuid, están tomados del código que cargará en la tarjeta del ESP32.
_________________________________
- Código.
https://github.com/nkolban/ESP32_BLE_Arduino/tree/7951347ed68313d75c367e1f2cce763cb56d1eb2/examples/BLE_write
- Consulta el Monitor Serie.
ble_enviar.ino |
/*
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
*/
// Modificado por Juan Antonio Villalpando.
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
String valor;
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
valor = "";
for (int i = 0; i < value.length(); i++){
// Serial.print(value[i]); // Presenta value.
valor = valor + value[i];
}
Serial.println("*********");
Serial.print("valor = ");
Serial.println(valor); // Presenta valor.
}
}
};
void setup() {
Serial.begin(115200);
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("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
// Serial.println("valor en el loop = ");
// Serial.println(valor); // Presenta valor.
}
|
_________________________________
3.- Reloj. La tarjeta ESP32 envía mediante BLE números aleatorios a App. Monitor Serie.
p110i_esp32_ble_recibir.aia
- El código de la tarjeta crea un número aleatorio del 0 al 100. Lo convierte en String.
- Cuando pulsamos el Botón de "Recibir" en App Inventor, recibimos un número aleatorio y se muestra en una Etiqueta.
- Los números aleatorios son creados cada 2 segundos.
- He querido mantener tanto el código de App Inventor como el de la tarjeta Wemos del ejemplo anterior, así que simplemente he modificado esos dos códigos, algunas líneas no son necesarias. El bloque de lectura es ReadStrings.
- En este ejemplo he puesto un Reloj.
- Consulta el Monitor Serie.
_________________________________
- Diseño.
_________________________________
- Bloques.
- Observa los números de serviceUuid y characteristicUuid, están tomados del código que cargará en la tarjeta.
_________________________________
- Código.
https://github.com/nkolban/ESP32_BLE_Arduino/tree/7951347ed68313d75c367e1f2cce763cb56d1eb2/examples/BLE_write
- Observa cómo toma el dato: pCharacteristic->setValue(alea.c_str()); // Pone el numero aleatorio
ble_recibir.ino |
/*
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
*/
// Modificado por Juan Antonio Villalpando.
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
String valor;
int aleatorio;
String alea = "2";
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
pCharacteristic->setValue(alea.c_str()); // Pone el numero aleatorio
if (value.length() > 0) {
valor = "";
for (int i = 0; i < value.length(); i++){
// Serial.print(value[i]); // Presenta value.
valor = valor + value[i];
}
Serial.println("*********");
Serial.print("valor = ");
Serial.println(valor); // Presenta valor.
}
}
};
void setup() {
Serial.begin(115200);
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("Iniciado.");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
//Serial.println("valor en el loop = ");
//Serial.println(valor); // Presenta valor.
aleatorio = random(1,100); // Crea el numero aleatorio.
alea = (String) aleatorio; // Lo convierte en String.
}
|
_________________________________
4.- BLE Server envía número aleatorio a App. Monitor Serie.
https://github.com/nkolban/ESP32_BLE_Arduino/tree/master/examples/BLE_server
p110_esp32_ble_server.aia
- Es un código similar al anterior, crea un número aleatorio del 0 al 100. Lo convierte en String.
- El Reloj de App Inventor chequea el valor de aleatorio cada 2 segundos.
- Observa el Monitor Serie.
_________________________________
- Diseño.
_________________________________
- Bloques.
_________________________________
- Código.
ble_server.ino |
/*
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
*/
// Modificado por Juan Antonio Villalpando.
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
String valor;
int aleatorio;
String alea = "2";
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
pCharacteristic->setValue(alea.c_str()); // Pone el numero aleatorio
Serial.println(alea);
}
};
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
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("Inicio.");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
aleatorio = random(1,100); // Crea el numero aleatorio.
alea = (String) aleatorio; // Lo convierte en String.
}
|
_________________________________
5.- Sin Reloj. App Inventor envía un dato cualquiera. BLE reenvía un número aleatorio.
p110i_esp32_ble_enviar_recibir.aia
- Observa que recibiremos una respuesta del módulo BLE y la tendremos en App Inventor sin utilizar el Reloj.
- Enviamos cualquier texto escrito en el CampoDeTexto al módulo BLE mediante "Envía información".
- Observaremos el texto enviado en el Monitor Serie.
- El módulo BLE genera un número aleatorio del 0 al 100, y nos lo devuelve. Se presenta en una Etiqueta.
_________________________________
- Diseño.
_________________________________
- Bloques.
_________________________________
- Código.
ble_envia_recibe.ino |
// Modificado por Juan Antonio Villalpando.
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
String valor;
int aleatorio;
String alea;
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
pCharacteristic->setValue(alea.c_str()); // Pone el numero aleatorio
if (value.length() > 0) {
valor = "";
for (int i = 0; i < value.length(); i++){
// Serial.print(value[i]); // Presenta value.
valor = valor + value[i];
}
Serial.println("*********");
Serial.print("valor = ");
Serial.println(valor); // Presenta valor.
}
}
};
void setup() {
Serial.begin(115200);
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("Iniciado.");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
delay(1000);
aleatorio = random(1,100); // Crea el numero aleatorio.
alea = (String) aleatorio; // Lo convierte en String.aleatorio
}
|
_________________________________
6.- Sin Reloj. App Inventor envía un dato. BLE reenvía un número aleatorio según el dato.
p110i_esp32_ble_enviar_recibir.aia (es el mismo código que el anterior)
- Si escribimos "uno" en el CampoDeTexto, nos devolverá un número aleatorio del 1 al 50.
- Si escribimos "dos" en el CampoDeTexto, nos devolverá un número aleatorio del 100 al 200.
- Si escribimos "tres" en el CampoDeTexto, nos devolverá dos números aleatorios, ejemplo (34,148)
- Si escribimos otra palabra, nos devolverá esa palabra.
- Observa el Monitor Serie.
ble_envia_recibe_2.ino |
// Modificado por Juan Antonio Villalpando.
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
String valor;
int aleatorio1;
int aleatorio2;
String alea1;
String alea2;
String alea3;
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
valor = "";
for (int i = 0; i < value.length(); i++){
// Serial.print(value[i]); // Presenta value.
valor = valor + value[i];
}
Serial.println("*********");
Serial.print("valor = ");
Serial.println(valor); // Presenta valor.
if(valor == "uno") {
pCharacteristic->setValue(alea1.c_str()); // Pone el numero aleatorio
}
if(valor == "dos") {
pCharacteristic->setValue(alea2.c_str()); // Pone el numero aleatorio
}
if(valor == "tres") {
pCharacteristic->setValue(alea3.c_str()); // Pone el numero aleatorio
}
}
}
};
void setup() {
Serial.begin(115200);
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("Iniciado.");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
delay(1000);
aleatorio1 = random(1,50); // Crea el numero aleatorio.
alea1 = (String) aleatorio1; // Lo convierte en String.aleatorio
aleatorio2 = random(100,200); // Crea el numero aleatorio.
alea2 = (String) aleatorio2; // Lo convierte en String.aleatorio
alea3 = alea1 + "," + alea2;
}
|
_________________________________
_________________________________
- Ejemplos con Notificación.
__________________________________________________________________
7.- Mediante Registry y Notificación. El ESP32 envía números aleatorios.
p110i_esp32_ble_notifica.aia
- En el ejemplo 4, vimos cómo el ESP32 generaba números aleatorios y App Inventor los recibía mediante el bloque ReadStrings y un Reloj. También debíamos utilizar el bloque WriteStrings para solicitarle la información.
- Ahora también el ESP32 va a generar números aleatorios, pero App Inventor los va a recibir de otra manera.
- Se utilizará el bloque RegisterForStrings, esta acción configurará a la extensión para que esté comprobando si hay un cambio de información recibida, sin utilizar el Reloj.
- El Bloque StringReceived, recibirá el valor enviado por el ESP32.
- El Reloj no es necesario en este código.
_________________________________
- Diseño.
_________________________________
- Bloques.
_________________________________
- Código.
- Basado en este código:
https://github.com/nkolban/ESP32_BLE_Arduino/blob/master/examples/BLE_notify/BLE_notify.ino
ble_notificacion.ino |
/*
Based on Neil Kolban example for IDF:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Ported to Arduino ESP32 by Evandro Copercini updated by chegewara
Create a BLE server that, once we receive a connection, will send periodic notifications.
A connect hander associated with the server starts a background task that performs notification
every couple of seconds.
*/
// Modificado por Juan A. Villalpando
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint32_t value = 0;
// 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"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
void setup() {
Serial.begin(115200);
// Create the BLE Device
BLEDevice::init("MyESP32");
// 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,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// https://www.bluetooth.com/specifications/gatt/viewer?
// attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
// Create a BLE Descriptor
pCharacteristic->addDescriptor(new BLE2902());
// Start the service
pService->start();
// Start advertising
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
BLEDevice::startAdvertising();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
// notify changed value
if (deviceConnected) {
// pCharacteristic->setValue((uint8_t*)&value, 4);
int aleatorio = random(1,100); // Crea el numero aleatorio.
String alea = (String) aleatorio; // Lo convierte en String.
pCharacteristic->setValue(alea.c_str()); // Pone el numero aleatorio
delay(500); // bluetooth stack will go into congestion, if too many packets are sent.
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}
|
_________________________________ no actualizado
8.- Mediante Registry y Notificación. El ESP32 envía números aleatorios. App Inventor envía números con un Deslizador.
p110_esp32_ble_notifica_Deslizador.aia
- Este ejemplo es la unión del ejemplo anterior, el 7 y el 2.
- En el ejemplo 7 acabamos de ver que el ESP32 envía un número aleatorio y App Inventor lo recibe como Notificación (sin utilizar reloj)
- El ejemplo 2 trataba de enviar una información desde App Inventor al ESP32
- En este ejemplo la información enviada desde App Inventor al ESP32 será un número creado por un Deslizador.
- El envío del número de App Inventor al ESP32 por una parte, y el envío de aleatorio desde ESP32 a App Inventor son independientes.
- En este ejemplo el bloque RegisterForStrings lo he puesto dentro del evento Connected.
- Ese número se verá en forma de caracter en el Monitor Serie.
- He probado los códigos en Android 5 y Android 9, fue mejor en el Android 5.
_________________________________
- Diseño.
_________________________________
- Bloques.
- Observa que he puesto solicitud de permiso.
- También he utilizado mi extensión para Habilitar y Deshabilitar el Bluetooth del móvil.
_________________________________
- Código.
ble_notificacion.ino |
/*
Video: https://www.youtube.com/watch?v=oCMOYS71NIU
Based on Neil Kolban example for IDF:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Ported to Arduino ESP32 by Evandro Copercini
updated by chegewara
Create a BLE server that, once we receive a connection, will send periodic notifications.
The service advertises itself as: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
And has a characteristic of: beb5483e-36e1-4688-b7f5-ea07361b26a8
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.
A connect hander associated with the server starts a background task that performs notification
every couple of seconds.
*/
// Modificado por Juan A. Villalpando
// KIO4.COM
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
String valor;
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
//uint32_t value = 0;
// 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"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
////////////////////// WriteStrings /////////////////////////////
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
valor = "";
for (int i = 0; i < value.length(); i++){
Serial.print(value[i]); // Presenta value.
valor = valor + value[i];
}
Serial.println();
Serial.print("valor = ");
Serial.println(valor); // Presenta valor.
Serial.println("*********");
}
}
};
///////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
// Create the BLE Device
BLEDevice::init("ESP32");
// 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,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// https://www.bluetooth.com/specifications/gatt/viewer?
// attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
// Create a BLE Descriptor
pCharacteristic->addDescriptor(new BLE2902());
// Esta línea es para el WriteStrings:
pCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
BLEDevice::startAdvertising();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
// notify changed value
if (deviceConnected) {
std::string value = pCharacteristic->getValue();
// pCharacteristic->setValue((uint8_t*)&value, 4);
int aleatorio = random(1,100); // Crea el numero aleatorio.
String alea = (String) aleatorio; // Lo convierte en String.
pCharacteristic->setValue(alea.c_str()); // Pone el numero aleatorio
pCharacteristic->notify();
// value++;
delay(500); // bluetooth stack will go into congestion, if too many packets are sent.
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}
|
_________________________________
9.- Mediante Registry y Notificación. App Inventor envía números mediante un Deslizador y ESP32 le devuelve el doble de ese número.
p110i_esp32_ble_notifica_Deslizador.aia (es la misma aplicación que la del ejemplo anterior)
- Mediante un Deslizador y el bloque WriteStrings, App Inventor envía un número del 1 al 100.
- Utilizamos el bloque RegisterForStrings, gracias a este bloque la aplicación está preparada para recibir un String por Bluetooth BLE sin necesidad de utilizar el Reloj.
- El código del ESP32 recibe el número y devuelve el doble del número recibido.
- Observarás que hay un pequeño retraso en el recibo del número.
- He probado los códigos en Android 5 y Android 9, fue mejor en el Android 5.
_________________________________
- Diseño.
_________________________________
- Bloques.
_________________________________
- Código.
ble_notificacion_envia_recibe_doble.ino |
/*
Video: https://www.youtube.com/watch?v=oCMOYS71NIU
Based on Neil Kolban example for IDF:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Ported to Arduino ESP32 by Evandro Copercini
updated by chegewara
Create a BLE server that, once we receive a connection, will send periodic notifications.
A connect hander associated with the server starts a background task that performs notification
every couple of seconds.
*/
// Modificado por Juan A. Villalpando
// http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
String valor;
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
//uint32_t value = 0;
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
////////////////////// WriteStrings /////////////////////////////
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
valor = "";
for (int i = 0; i < value.length(); i++){
// Serial.print(value[i]); // Presenta value.
valor = valor + value[i];
}
Serial.println("*********");
Serial.print("valor = ");
Serial.println(valor); // Presenta valor.
}
}
};
///////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
// Create the BLE Device
BLEDevice::init("MyESP32");
// 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,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// https://www.bluetooth.com/specifications/gatt/viewer?
// attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
// Create a BLE Descriptor
pCharacteristic->addDescriptor(new BLE2902());
// Esta línea es para el WriteStrings:
pCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0); // set value to 0x00 to not advertise this parameter
BLEDevice::startAdvertising();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
// notify changed value
if (deviceConnected) {
std::string value = pCharacteristic->getValue();
// pCharacteristic->setValue((uint8_t*)&value, 4);
int doble = valor.toInt() * 2 ;
String doblado = (String) doble; // Lo convierte en String.
pCharacteristic->setValue(doblado.c_str()); // Pone el numero doble
pCharacteristic->notify();
// value++;
delay(5); // bluetooth stack will go into congestion, if too many packets are sent.
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}
|
______________________________________________
- Generador de UUID para BLE.
- Cada servicio, característica y descriptor tiene un UUID (Universally Unique Identifier). Un UUID es un número único de 16 bytes.
- Hay algunos UUID normalizados: SIG (Bluetooth Special Interest Group).
- Pero podemos crearnos unos UUID personales para nuestra aplicación: UUID generator.
_______________________________
|