Android: Envío de datos> 20 bytes by BLE

Puedo enviar datos hasta 20 bytes conectándome a un dispositivo BLE externo. ¿Cómo puedo enviar datos de más de 20 bytes. He leído que tenemos que fragmentar los datos o dividir la característica de las partes necesarias. Si supongo que mis datos son de 32 bytes, ¿podría decirme los cambios que necesito hacer en mi código para que esto funcione? Los siguientes son los fragmentos necesarios de mi código:

public boolean send(byte[] data) { if (mBluetoothGatt == null || mBluetoothGattService == null) { Log.w(TAG, "BluetoothGatt not initialized"); return false; } BluetoothGattCharacteristic characteristic = mBluetoothGattService.getCharacteristic(UUID_SEND); if (characteristic == null) { Log.w(TAG, "Send characteristic not found"); return false; } characteristic.setValue(data); characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); return mBluetoothGatt.writeCharacteristic(characteristic); } 

Este es el código que usé para enviar los datos. La función "enviar" se utiliza en el siguiente evento onclick.

 sendValueButton = (Button) findViewById(R.id.sendValue); sendValueButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String text = dataEdit.getText().toString(); yableeService.send(text.getBytes()); } }); 

Cuando el String text es mayor de 20 bytes, sólo se reciben los primeros 20 bytes. ¿Cómo rectificar esto?

Para probar el envío de múltiples características He intentado esto:

 sendValueButton = (Button) findViewById(R.id.sendValue); sendValueButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String text = "Test1"; yableeService.send(text.getBytes()); text = "Test2"; yableeService.send(text.getBytes()); text = "Test3"; yableeService.send(text.getBytes()); } }); 

Pero sólo recibí "Test3", es decir, la última característica. ¿Qué error cometí? Soy nuevo en BLE así que por favor ignora cualquier ingenuidad

Editar:

Después de aceptar la respuesta para cualquiera que ve esto más tarde.

Hay dos maneras de lograr esto. 1. Divida sus datos y escriba en un bucle como hace la respuesta seleccionada. 2. Divida sus datos y escriba utilizando la devolución de llamada, es decir, onCharacterisitcWrite() . Esto le ahorrará de errores si había alguno durante la escritura.

Pero lo más importante entre las escrituras utiliza un Thread.sleep(200) si sólo está escribiendo y no espera una respuesta del firmware. Esto asegurará que todos sus datos alcancen. Sin el sleep siempre estaba recibiendo el último paquete. Si usted nota la respuesta aceptada él también ha utilizado el sleep en medio.

BLE permite transferir máximo es de 20 bytes.

Si desea enviar más 20 bytes, debe definir array byte [] incluir cuántos paquetes desea.

El ejemplo funcionó bien si desea enviar <160 caracteres (160 bytes).

P / s: Deje editar seguido como u quiere. No me siguió exactamente.

En realidad, cuando estamos usando BLE, lateral móvil y el lado del firmware necesidad de configurar la clave (por ejemplo, 0x03 …) para definir la puerta de conexión entre ambos lados.

La idea es:

  • Cuando seguimos transfiriendo paquetes, no es el último. La puerta es byte[1] = 0x01 .

  • Si enviamos el último, La puerta es byte[1] = 0x00 .

La construcción de datos (20 bytes):

1 – Byte 1 – Definir la Gate ID : ex. byte[0] = 0x03 ID de puerta de mensaje byte[0] = 0x03 .

2 – Byte 2 – Definir el recognization : Es el último paquete 0x00 o continuar enviando paquetes 0x01 .

3 – Byte 3 (Debe ser 18 bytes después de menos Byte 1 y Byte 2 ) – Adjuntar el contenido del mensaje aquí.

Debería entender mi lógica antes de leer el código de abajo por favor.

A continuación se muestra un ejemplo de enviar Mensaje con muchos paquetes, cada paquete: byte [20].

 private void sendMessage(BluetoothGattCharacteristic characteristic, String CHARACTERS){ byte[] initial_packet = new byte[3]; /** * Indicate byte */ initial_packet[0] = BLE.INITIAL_MESSAGE_PACKET; if (Long.valueOf( String.valueOf(CHARACTERS.length() + initial_packet.length)) > BLE.DEFAULT_BYTES_VIA_BLE) { sendingContinuePacket(characteristic, initial_packet, CHARACTERS); } else { sendingLastPacket(characteristic, initial_packet, CHARACTERS); } } private void sendingContinuePacket(BluetoothGattCharacteristic characteristic, byte[] initial_packet, String CHARACTERS){ /** * TODO If data length > Default data can sent via BLE : 20 bytes */ // Check the data length is large how many times with Default Data (BLE) int times = Byte.valueOf(String.valueOf( CHARACTERS.length() / BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET)); Log.i(TAG, "CHARACTERS.length() " + CHARACTERS.length()); Log.i(TAG, "times " + times); // TODO // 100 : Success // 101 : Error byte[] sending_continue_hex = new byte[BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET]; for (int time = 0; time <= times; time++) { /** * Wait second before sending continue packet */ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } if (time == times) { Log.i(TAG, "LAST PACKET "); /** * If can not have enough characters to send continue packet, * This is the last packet will be sent to the band */ /** * Packet length byte : */ /** * Length of last packet */ int character_length = CHARACTERS.length() - BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET*times; initial_packet[1] = Byte.valueOf(String.valueOf(character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH)); initial_packet[2] = BLE.SENDING_LAST_PACKET; Log.i(TAG, "character_length " + character_length); /** * Message */ // Hex file byte[] sending_last_hex = new byte[character_length]; // Hex file : Get next bytes for (int i = 0; i < sending_last_hex.length; i++) { sending_last_hex[i] = CHARACTERS.getBytes()[sending_continue_hex.length*time + i]; } // Merge byte[] byte[] last_packet = new byte[character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH]; System.arraycopy(initial_packet, 0, last_packet, 0, initial_packet.length); System.arraycopy(sending_last_hex, 0, last_packet, initial_packet.length, sending_last_hex.length); // Set value for characteristic characteristic.setValue(last_packet); } else { Log.i(TAG, "CONTINUE PACKET "); /** * If have enough characters to send continue packet, * This is the continue packet will be sent to the band */ /** * Packet length byte */ int character_length = sending_continue_hex.length; /** * TODO Default Length : 20 Bytes */ initial_packet[1] = Byte.valueOf(String.valueOf( character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH)); /** * If sent data length > 20 bytes (Default : BLE allow send 20 bytes one time) * -> set 01 : continue sending next packet * else or if after sent until data length < 20 bytes * -> set 00 : last packet */ initial_packet[2] = BLE.SENDING_CONTINUE_PACKET; /** * Message */ // Hex file : Get first 17 bytes for (int i = 0; i < sending_continue_hex.length; i++) { Log.i(TAG, "Send stt : " + (sending_continue_hex.length*time + i)); // Get next bytes sending_continue_hex[i] = CHARACTERS.getBytes()[sending_continue_hex.length*time + i]; } // Merge byte[] byte[] sending_continue_packet = new byte[character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH]; System.arraycopy(initial_packet, 0, sending_continue_packet, 0, initial_packet.length); System.arraycopy(sending_continue_hex, 0, sending_continue_packet, initial_packet.length, sending_continue_hex.length); // Set value for characteristic characteristic.setValue(sending_continue_packet); } // Write characteristic via BLE mBluetoothGatt.writeCharacteristic(characteristic); } } public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic, String data) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return false; } if (ActivityBLEController.IS_FIRST_TIME) { /** * In the first time, * should send the Title */ byte[] merge_title = sendTitle(data); // Set value for characteristic characteristic.setValue(merge_title); // Write characteristic via BLE mBluetoothGatt.writeCharacteristic(characteristic); // Reset ActivityBLEController.IS_FIRST_TIME = false; return true; } else { /** * In the second time, * should send the Message */ if (data.length() <= BLE.LIMIT_CHARACTERS) { sendMessage(characteristic, data); // Reset ActivityBLEController.IS_FIRST_TIME = true; return true; } else { // Typed character typed_character = data.length(); return false; } } } 

En Lollipop puede enviar hasta 512 bytes. Necesita usar BluetoothGatt.requestMtu() con un valor de 512. Además, como @Devunwired ha mencionado, debe esperar hasta que se complete cualquier operación anterior antes de llamar a esto.

Está correcto que la especificación BLE no permite que las operaciones de escritura excedan 20 bytes. Si no puede subdividir su carga útil en varias características (que lógicamente va a ser más fácil de mantener), entonces su mecanismo de fragmentación es el otro enfoque.

Sin embargo, compruebe que la pila BLE odia cuando intenta hacer cola varias operaciones. Cada lectura / escritura es asíncrona, cuyo resultado viene a través de la onCharacteristicRead() o onCharacteristicWrite() en la instancia de BluetoothGattCallback . El código que ha escrito intenta enviar tres operaciones de escritura características una encima de la otra, sin esperar a que la devolución de llamada entre. Su código necesitará seguir un camino más parecido a:

 send(Test1) -> Wait for onCharacteristicWrite() -> send(Test2) -> Wait for onCharacteristicWrite() -> send(Test3) -> Wait for onCharacteristicWrite() Done! 

En realidad, puede desencadenar una escritura BLE Long si el dispositivo en el otro extremo lo admite.

Puede hacerlo configurando el tipo de escritura como BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT

En este caso, puede enviar más de 20 bytes.

Si desea enviar grandes conjuntos de datos a través de BLE, entonces su mejor opción es utilizar dos características, una para enviar la mayor parte de sus datos y la otra para enviar el último segmento. De esta manera, no es necesario establecer la respuesta a WRITE_NO_RESPONSE y utilizar la devolución de llamada para enviar el siguiente segmento hasta el último segmento, momento en el que se escribirá que a la segunda característica que permitirá que el dispositivo sabe Que ha terminado de escribir los datos y que puede concatenar todos los datos juntos para formar un gran paquete de datos.

Hay un montón de equivocaciones aquí.

BLE es capaz de enviar mucho más de 20 bytes, y se puede hacer fácilmente en android.

Lo que hay que cambiar es el enlace MTU que se establece en 23 por defecto (sólo 20 de ellos se pueden utilizar para establecer un valor). Android proporciona el mecanismo de fragmentación si el paquete dado para enviar es mayor que el MTU actual (este es el propósito del parámetro offset en la onCharacteristicRead(...) ).

Así que usted puede hacer la MTU más grande, como una solicitud de la central utilizando: requestMtu(...) API. Este último provocará una llamada callback onMtuChanged en el lado periférico que le informará de la nueva MTU. Una vez realizada esta acción, puede enviar paquetes más grandes sin emitir el mecanismo de fragmentación de Android.

Las alternativas son construir tu propio mecanismo de fragmentación y no enviar paquetes que sean más grandes que el MTU. O confiar en el mecanismo de Android y trabajar con él con el parámetro 'offset'.

Este es el ejemplo de la implementación usando el método chunk, pero sin usar Thread.sleep , encontré que es mejor y más eficiente para mi aplicación enviar más de 20 bits de datos.

Los paquetes se enviarán después de onCharacteristicWrite() . Acabo de descubrir que este método se activará automáticamente después de que el dispositivo periférico (BluetoothGattServer) envíe un método sendResponse() .

En primer lugar tenemos que transformar los datos de paquetes en trozos con esta función:

 public void sendData(byte [] data){ int chunksize = 20; //20 byte chunk packetSize = (int) Math.ceil( data.length / (double)chunksize); //make this variable public so we can access it on the other function //this is use as header, so peripheral device know ho much packet will be received. characteristicData.setValue(packetSize.toString().getBytes()); mGatt.writeCharacteristic(characteristicData); mGatt.executeReliableWrite(); packets = new byte[packetSize][chunksize]; packetInteration =0; Integer start = 0; for(int i = 0; i < packets.length; i++) { int end = start+chunksize; if(end>data.length){end = data.length;} packets[i] = Arrays.copyOfRange(data,start, end); start += chunksize; } 

Después de que nuestros datos estén listos, así que pongo mi iteración en esta función:

 @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if(packetInteration<packetSize){ characteristicData.setValue(packets[packetInteration]); mGatt.writeCharacteristic(characteristicData); packetInteration++; } } 
  • Error en el archivo xml de maven pom: Creando un proyecto Android
  • Obtener fecha de un mensaje SMS android
  • Android Almacenamiento interno VS Preferencias compartidas
  • ¿Cómo comprobar si el paquete existe desde dentro del procesador de anotación (en tiempo de compilación)?
  • Creación de una función personalizada en sqlite3 en android
  • Convertir archivos C ++ (.h y .cpp) existentes en java para Android
  • Problema de exactitud de Google maps
  • ¿Puedo desarrollar aplicaciones de Android sin IDE?
  • Toma una captura de pantalla en Android
  • Quitar la sombra de ActionBar en Android L (API 21)
  • E.printStackTrace (); En cuerda
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.