fbpixel
Etiquetas: , , ,
0
(0)

Bluetooth Low Energy (BLE) tiene un límite conocido de 20Bytes en la longitud de las cadenas enviadas. Hay formas de anular este límite.

Hardware

En este tutorial, enviaremos datos desde una aplicación Android, desarrollada con React Native, a un ESP32. Los métodos descritos también pueden ser válidos para otros dispositivos.

  • Dispositivo Android
  • ESP32 BLE

BLE limitado a 20 bytes

La aplicación desarrollada bajo React Native es perfectamente capaz de enviar cadenas de caracteres largas en forma de paquete de 20bytes por defecto. Sin modificar el tutorial anterior, este es el valor recibido en el lado del ESP32. Sólo se almacena en memoria el último paquete.

01:48:39.734 -> ESP32BLE server ready
01:48:40.493 -> Server address:3c:61:05:31:5f:12
01:48:41.672 -> Client connected
01:48:48.169 -> Charac value: Helloworldthisisalon
01:48:48.253 -> Charac value: gstringletseewhatcom
01:48:48.374 -> Charac value: esout;
01:48:48.374 -> this is the last packet

Resumen de métodos para enviar cadenas largas a través de BLE

  • Recuperar varios paquetes (en el lado del receptor)
  • Enviar la cadena larga en forma de paquetes pequeños (lado emisor)
  • Aumentar el límite de MTU de 23 bytes a 512 bytes

Recuperar varios paquetes

Si el dispositivo que envía los mensajes es capaz de gestionar el envío de cadenas de caracteres que superan el límite de la MTU, como es el caso de nuestro ejemplo, sólo queda configurar el módulo receptor para que concatene los distintos paquetes recibidos. Para ello, utilizaremos un carácter de fin de cadena, como «;».

En la función onWrite de la característica del módulo ESP32BLE, añadimos un test de fin de cadena y una variable longMsg para que actúe como buffer.

std::string longMsg;
class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();

      if (value.length() > 0) {
        Serial.print("Charac value: ");
        for (int i = 0; i < value.length(); i++)
          Serial.print(value[i]);

        Serial.println();
        if(value.find(";") != -1){
          //Serial.println("this is the last packet");
          longMsg = longMsg + value;
          Serial.print("longMsg: ");
          for (int i = 0; i < longMsg.length(); i++)
            Serial.print(longMsg[i]);
          Serial.println();
          //do whatever you want with longMsg then erase
          longMsg = "";
        }else{
          longMsg = longMsg + value;
        }
      }
    }
};

Envío de paquetes de tamaño predefinido

Si el dispositivo que envía los datos no gestiona mensajes de tamaño superior a la MTU, es posible dividir la cadena de caracteres en paquetes de tamaño predefinido (chunksize). Este método permite controlar el tamaño de los paquetes enviados.

En el proyecto React Native, estamos creando una función que transformará la cadena de caracteres largos en un array de bytes que enviaremos en paquetes.

    const sendLongMessage = async (data: string, chunksize: number) => {
      console.log("data : ",data)
      var bytes = convertStringToByteArray(data)
      var times = Math.ceil(bytes.length/chunksize);
        var packets = [];
  
        console.log("split data ",times," times");
        //console.log("bytes: ",bytes)
        var i=0
        for(var time=0;time<times;time++){
          var packet = bytes.slice(time*chunksize, (time+1)*chunksize)
          packets.push(packet)
          console.log(time," : ",byteArrayToString(packet))
          sendMessage(byteArrayToString(packet));
          await delay(100);
        }
    }

N.B.: se puede introducir una función de retardo para dar tiempo a que se envíe el mensaje. delay(100)

const delay = (ms: number) => new Promise(
  resolve => setTimeout(resolve, ms)
);

Aumentar el límite de MTU de la aplicación

Por defecto, la librería react-native-ble-manager envía paquetes de 20bytes. Existe un método para especificar que el módulo BLE debe modificar el tamaño de la Unidad Máxima de Transmisión (MTU)

En el código de la aplicación, durante la conexión, antes de recuperar los servicios, añada una solicitud de MTU

BleManager.requestMTU(device.id, 512).then(
        (mtu) => {
          setMTU(mtu);
        }
      ) //request the MTU size in bytes

Al enviar el mensaje, puedes especificar el tamaño máximo del mensaje en bytes, «mtu», en la función BLEManager.write().

     BleManager.write(
       selectedDevice.id,
       serviceid,
       caracid,
       buffer.toJSON().data,
       mtu // or 512
     ).then(() => {
       // Success code
       console.log("Write: " + buffer.toJSON().data);
     })

En el lado ESP32, hay un método en la biblioteca BLEDevice para definir el tamaño de MTU.

BLEDevice::setMTU(512); //between 23 and 517 (bluetooth 4.2)

N.B.: En este ejemplo (Android+ESP32), la única forma de aumentar el límite es definir el número máximo de bytes en la función BLEManager.write(). Dejaremos el resto de información que pueda ser útil para otra configuración (iOS, HM10, etc.).

Una vez modificado el código, cuando devolvamos la misma cadena de caracteres, recibiremos su valor completo en la función BLE

Aplicaciones

  • Aumentar el tamaño de los mensajes enviados al módulo BLE
  • Imitar el funcionamiento de Bluetooth classic de forma puntual

Fuentes

¿De cuánta utilidad te ha parecido este contenido?

¡Haz clic en una estrella para puntuarlo!

Promedio de puntuación 0 / 5. Recuento de votos: 0

Hasta ahora, ¡no hay votos!. Sé el primero en puntuar este contenido.

Ya que has encontrado útil este contenido...

¡Sígueme en los medios sociales!

¡Siento que este contenido no te haya sido útil!

¡Déjame mejorar este contenido!

Dime, ¿cómo puedo mejorar este contenido?