Back to project page BetterBluetoothLE.
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.
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())); } }