UART divides long text into 20B parts

UART now checks the RX characteristic properties and:
1) it will use long write if WRITE REQUEST is set,
2) it will divide the text into up to 20-bytes packets
Also the app background has been fixed.
This commit is contained in:
Aleksander Nowakowski
2015-08-17 16:44:16 +02:00
parent 54507a1017
commit 341ecf5781
35 changed files with 316 additions and 75 deletions

View File

@@ -340,6 +340,7 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) == 0)
return false;
Logger.d(mLogSession, "gatt.setCharacteristicNotification(" + characteristic.getUuid() + ", true)");
gatt.setCharacteristicNotification(characteristic, true);
final BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID);
if (descriptor != null) {
@@ -366,6 +367,7 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) == 0)
return false;
Logger.d(mLogSession, "gatt.setCharacteristicNotification(" + characteristic.getUuid() + ", true)");
gatt.setCharacteristicNotification(characteristic, true);
final BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID);
if (descriptor != null) {
@@ -414,7 +416,7 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
if ((properties & (BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) == 0)
return false;
Logger.v(mLogSession, "Writing characteristic " + characteristic.getUuid());
Logger.v(mLogSession, "Writing characteristic " + characteristic.getUuid() + " (" + getWriteType(characteristic.getWriteType()) + ")");
Logger.d(mLogSession, "gatt.writeCharacteristic(" + characteristic.getUuid() + ")");
return gatt.writeCharacteristic(characteristic);
}
@@ -921,4 +923,17 @@ public abstract class BleManager<E extends BleManagerCallbacks> {
return "UNKNOWN";
}
}
private String getWriteType(final int type) {
switch (type) {
case BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT:
return "WRITE REQUEST";
case BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE:
return "WRITE COMMAND";
case BluetoothGattCharacteristic.WRITE_TYPE_SIGNED:
return "WRITE SIGNED";
default:
return "UNKNOWN: " + type;
}
}
}

View File

@@ -26,7 +26,9 @@ import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.text.TextUtils;
import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
@@ -36,12 +38,16 @@ import no.nordicsemi.android.nrftoolbox.profile.BleManager;
public class UARTManager extends BleManager<UARTManagerCallbacks> {
/** Nordic UART Service UUID */
private final static UUID UART_SERVICE_UUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
/** TX characteristic UUID */
private final static UUID UART_TX_CHARACTERISTIC_UUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
/** RX characteristic UUID */
private final static UUID UART_RX_CHARACTERISTIC_UUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
private final static UUID UART_RX_CHARACTERISTIC_UUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
/** TX characteristic UUID */
private final static UUID UART_TX_CHARACTERISTIC_UUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");
/** The maximum packet size is 20 bytes. */
private static final int MAX_PACKET_SIZE = 20;
private BluetoothGattCharacteristic mTXCharacteristic, mRXCharacteristic;
private BluetoothGattCharacteristic mRXCharacteristic, mTXCharacteristic;
private byte[] mOutgoingBuffer;
private int mBufferOffset;
public UARTManager(final Context context) {
super(context);
@@ -60,7 +66,7 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
@Override
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
requests.push(Request.newEnableNotificationsRequest(mRXCharacteristic));
requests.push(Request.newEnableNotificationsRequest(mTXCharacteristic));
return requests;
}
@@ -68,22 +74,51 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
public boolean isRequiredServiceSupported(final BluetoothGatt gatt) {
final BluetoothGattService service = gatt.getService(UART_SERVICE_UUID);
if (service != null) {
mTXCharacteristic = service.getCharacteristic(UART_TX_CHARACTERISTIC_UUID);
mRXCharacteristic = service.getCharacteristic(UART_RX_CHARACTERISTIC_UUID);
mTXCharacteristic = service.getCharacteristic(UART_TX_CHARACTERISTIC_UUID);
}
return mTXCharacteristic != null && mRXCharacteristic != null;
boolean writeRequest = false;
boolean writeCommand = false;
if (mRXCharacteristic != null) {
final int rxProperties = mRXCharacteristic.getProperties();
writeRequest = (rxProperties & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0;
writeCommand = (rxProperties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0;
// Set the WRITE REQUEST type when the characteristic supports it. This will allow to send long write (also if the characteristic support it).
// In case there is no WRITE REQUEST property, this manager will divide texts longer then 20 bytes into up to 20 bytes chunks.
if (writeRequest)
mRXCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
}
return mRXCharacteristic != null && mTXCharacteristic != null && (writeRequest || writeCommand);
}
@Override
protected void onDeviceDisconnected() {
mTXCharacteristic = null;
mRXCharacteristic = null;
mTXCharacteristic = null;
}
@Override
public void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
final String data = characteristic.getStringValue(0);
mCallbacks.onDataSent(data);
// When the whole buffer has been sent
final byte[] buffer = mOutgoingBuffer;
if (mBufferOffset == buffer.length) {
try {
mCallbacks.onDataSent(new String(buffer, "UTF-8"));
} catch (final UnsupportedEncodingException e) {
// do nothing
}
mOutgoingBuffer = null;
} else { // Otherwise...
final int length = Math.min(buffer.length - mBufferOffset, MAX_PACKET_SIZE);
final byte[] data = new byte[length]; // We send at most 20 bytes
System.arraycopy(buffer, mBufferOffset, data, 0, length);
mBufferOffset += length;
mRXCharacteristic.setValue(data);
writeCharacteristic(mRXCharacteristic);
}
}
@Override
@@ -100,13 +135,30 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
}
/**
* Sends the given text to TH characteristic.
* Sends the given text to RX characteristic.
* @param text the text to be sent
*/
public void send(final String text) {
if (mTXCharacteristic != null) {
mTXCharacteristic.setValue(text);
writeCharacteristic(mTXCharacteristic);
// An outgoing buffer may not be null if there is already another packet being sent. We do nothing in this case.
if (!TextUtils.isEmpty(text) && mOutgoingBuffer == null) {
final byte[] buffer = mOutgoingBuffer = text.getBytes();
mBufferOffset = 0;
// Depending on whether the characteristic has the WRITE REQUEST property or not, we will either send it as it is (hoping the long write is implemented),
// or divide it into up to 20 bytes chunks and send them one by one.
final boolean writeRequest = (mRXCharacteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0;
if (!writeRequest) { // no WRITE REQUEST property
final int length = Math.min(buffer.length, MAX_PACKET_SIZE);
final byte[] data = new byte[length]; // We send at most 20 bytes
System.arraycopy(buffer, 0, data, 0, length);
mBufferOffset += length;
mRXCharacteristic.setValue(data);
} else { // there is WRITE REQUEST property
mRXCharacteristic.setValue(buffer);
mBufferOffset = buffer.length;
}
writeCharacteristic(mRXCharacteristic);
}
}
}