Android Open Source - BetterBluetoothLE U A R T






From Project

Back to project page BetterBluetoothLE.

License

The source code is released under:

MIT License

If you think the Android project BetterBluetoothLE listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package betterbluetoothle.services;
/*ww  w  .j a v  a  2s. com*/
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.content.Context;

import com.google.common.base.Function;
import com.google.common.primitives.Bytes;

import org.jdeferred.DoneCallback;
import org.jdeferred.DonePipe;
import org.jdeferred.ProgressCallback;
import org.jdeferred.Promise;
import org.jdeferred.impl.DeferredObject;

import java.nio.charset.Charset;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.UUID;

import betterbluetoothle.async.AsyncBluetoothGatt;
import betterbluetoothle.async.AsyncBluetoothLeScan;

public class UART {

    //
    // PUBLIC METHODS AND STATE
    //

    // UUIDs for UAT service and associated characteristics.
    public static UUID UART_UUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E");
    public static UUID TX_UUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E");
    public static UUID RX_UUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E");

    // Constructor
    public UART(BluetoothDevice device, Context context, boolean autoConnect) {
        gatt = new AsyncBluetoothGatt(device, context, autoConnect);
        received = new ArrayDeque<Byte>();
    }

    // Static method to find the first nearby UART device.
    // When this promise is resolved the first available UART device has been found.
    public static Promise<UART, Void, Void> findFirst(BluetoothAdapter adapter, final Context context, final boolean autoConnect) {
        scanner = new AsyncBluetoothLeScan(adapter);
        found = new DeferredObject<UART, Void, Void>();
        // Scan for devices with the UART service.
        scanner.start(UART_UUID).progress(new ProgressCallback<AsyncBluetoothLeScan.ScanResult>() {
            @Override
            public void onProgress(AsyncBluetoothLeScan.ScanResult progress) {
                // Found a device.
                // Stop the scan.
                scanner.stop();
                scanner = null;
                // Resolve the found promise with the UART.
                found.resolve(new UART(progress.device, context, autoConnect));
            }
        });
        return found.promise();
    }

    // Connect to the device's UART service and setup code to fire connected, available, and
    // disconnected promises.
    public void connect() {
        // Connect to the device.
        gatt.connect().then(new DonePipe<Void, Void, Integer, Void>() {
            @Override
            public Promise<Void, Integer, Void> pipeDone(Void result) {
                // Connected, start service discovery.
                return gatt.discoverServices();
            }
        // Switch to promise for service discovery completion.
        }).then(new DonePipe<Void, BluetoothGattDescriptor, Integer, Void>() {
            @Override
            public Promise<BluetoothGattDescriptor, Integer, Void> pipeDone(Void result) {
                // Service discovery complete, grab reference to TX and RX services.
                rx = gatt.getService(UART_UUID).getCharacteristic(RX_UUID);
                tx = gatt.getService(UART_UUID).getCharacteristic(TX_UUID);
                // Notify that device is connected.
                enumerateCallbacks(new Function<Callback, Void>() {
                    @Override
                    public Void apply(Callback input) {
                        input.connected();
                        return null;
                    }
                });
                // Now setup notifications for RX characteristic changes.
                // First change the client descriptor to enable notifications and write it to the device.
                BluetoothGattDescriptor client = rx.getDescriptor(CLIENT_UUID);
                client.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                return gatt.writeDescriptor(client);
            }
            // Switch to promise for RX client descriptor update.
        }).then(new DonePipe<BluetoothGattDescriptor, Void, Void, BluetoothGattCharacteristic>() {
            @Override
            public Promise<Void, Void, BluetoothGattCharacteristic> pipeDone(BluetoothGattDescriptor result) {
                // Descriptor update complete, now enable notifications on RX characteristic changes.
                return gatt.setCharacteristicNotification(rx, true);
            }
            // Switch to promise for RX characteristic updates (i.e. data received).
        }).progress(new ProgressCallback<BluetoothGattCharacteristic>() {
            @Override
            public void onProgress(BluetoothGattCharacteristic progress) {
                // RX characteristic has changed.
                // Update buffer of received bytes.
                updateReceived(progress);
                // Notify data is available for reading.
                enumerateCallbacks(new Function<Callback, Void>() {
                    @Override
                    public Void apply(Callback input) {
                        input.available();
                        return null;
                    }
                });

            }
        });
        // Catch when the device is disconnected and notify all the registered callbacks.
        gatt.disconnected().done(new DoneCallback<Void>() {
                @Override
                public void onDone(Void result) {
                    // Notify disconnected
                    enumerateCallbacks(new Function<Callback, Void>() {
                        @Override
                        public Void apply(Callback input) {
                            input.disconnected();
                            return null;
                        }
                    });
                }
            }
        );
    }

    // Interface to define the UART event handler functions for connected, disconnected, and data
    // available events.
    public interface Callback {
        public void connected();
        public void disconnected();
        public void available();
    }

    // Register a class to receive callbacks of UART events.
    public synchronized void register(Callback callback) {
        // Add the callback if it isn't already in the list of registered callbacks.
        if (!callbacks.contains(callback)) {
            callbacks.add(callback);
        }
    }

    // Unregister a class to stop receiving callbacks of UART events.
    public synchronized void unregister(Callback callback) {
        // Remove the callback.
        callbacks.remove(callback);
    }

    // Return amount of bytes available in received buffer.
    public synchronized int available() {
        return received.size();
    }

    // Disconnect from the UART.
    public void disconnect() {
        gatt.disconnect();
    }

    // Write bytes to the UART.
    public void write(byte[] data) {
        if (tx == null) {
            return;
        }
        tx.setValue(data);
        gatt.writeCharacteristic(tx);
    }

    // Write a string to the UART.  String will be encoded in UTF-8 before sending to UART.
    public void write(String data) {
        write(data.getBytes(Charset.forName("UTF-8")));
    }

    // Read up to count bytes of data from the UART received data.  Less data than requested might be returned!
    public synchronized byte[] read(int count) {
        int size = count < received.size() ? count : received.size();
        byte[] result = new byte[size];
        for (int i = 0; i < size; ++i) {
            result[i] = received.remove();
        }
        return result;
    }

    // Read all bytes of data from the UART.
    public synchronized byte[] readAll() {
        byte[] result = Bytes.toArray(received);
        received.clear();
        return result;
    }

    // Read bytes as a UTF-8 string up to length bytes long.  Less data than requested might be returned!
    public synchronized String readString(int length) {
        return new String(read(length), Charset.forName("UTF-8"));
    }

    // Read all bytes as a UTF-8 string.
    public synchronized String readAllString() {
        return new String(readAll(), Charset.forName("UTF-8"));
    }

    //
    // PRIVATE/INTERNAL METHODS AND STATE
    //

    // UUID for the BTLE client characteristic which is necessary for notifications.
    private static UUID CLIENT_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");

    private static AsyncBluetoothLeScan scanner;
    private static DeferredObject<UART, Void, Void> found;
    private AsyncBluetoothGatt gatt;
    private BluetoothGattCharacteristic rx;
    private BluetoothGattCharacteristic tx;
    // TODO: This deque of bytes is not efficient for storing the buffer of received data.
    private ArrayDeque<Byte> received;
    private ArrayList<Callback> callbacks;

    // Convenience method for enumerating all valid callbacks.
    private synchronized void enumerateCallbacks(Function<Callback, Void> function) {
        for (Callback callback : callbacks) {
            if (callback != null) {
                function.apply(callback);
            }
        }
    }

    // Add data to received buffer.
    private synchronized void updateReceived(BluetoothGattCharacteristic rx) {
        received.addAll(Bytes.asList(rx.getValue()));
    }
}




Java Source Code List

betterbluetoothle.async.AsyncBluetoothGatt.java
betterbluetoothle.async.AsyncBluetoothLeScan.java
betterbluetoothle.services.UART.java