25

I am able to discover, connect to bluetooth.

Source Code---

Connect via bluetooth to Remote Device:

//Get the device by its serial number
 bdDevice = mBluetoothAdapter.getRemoteDevice(blackBox);

 //for ble connection
 bdDevice.connectGatt(getApplicationContext(), true, mGattCallback);

Gatt CallBack for Status:

 private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
    //Connection established
    if (status == BluetoothGatt.GATT_SUCCESS
        && newState == BluetoothProfile.STATE_CONNECTED) {

        //Discover services
        gatt.discoverServices();

    } else if (status == BluetoothGatt.GATT_SUCCESS
        && newState == BluetoothProfile.STATE_DISCONNECTED) {

        //Handle a disconnect event

    }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {

    //Now we can start reading/writing characteristics

    }
};

Now I want to send commands to Remote BLE device but don't know how to do that.

Once the command is sent to the BLE device, the BLE device will respond by broadcasting data which my application can receive.

sjain
  • 23,126
  • 28
  • 107
  • 185
  • 1
    I'm not familiar with Android, more with iOS, and I worked with BLE. But you can't only write on characteristic (if allowed). So you need to discover characteristic. The logic is like that : Peripheral -> Service(s) -> Characteristic(s). – Larme Apr 30 '14 at 17:14
  • @Larme:does that mean apple does allow the writing as specified in bluetooth specs for gatt - especially custom gatt profiles? Did you succeed in 2 way communication with corebluetooth without MFI membership? – andreas-supersmart Sep 30 '14 at 14:31
  • 1
    @andreas-manusm: Yes, you can. – Larme Sep 30 '14 at 14:34
  • I have similar doubt can anyone see link and respond on that http://stackoverflow.com/questions/38935479/how-to-send-command-to-ble-device-and-show-result – RAJAT SINGH Aug 13 '16 at 20:03

2 Answers2

15

You need to break this process into a few steps, when you connect to a BLE device and discover Services:

  1. Display available gattServices in onServicesDiscovered for your callback

  2. To check whether you can write a characteristic or not
    check for BluetoothGattCharacteristic PROPERTIES -I didn't realize that need to enable the PROPERTY_WRITE on the BLE hardware and that wasted a lot of time.

  3. When you write a characteristic, does the hardware perform any action to explicitly indicate the operation (in my case i was lighting an led)

Suppose mWriteCharacteristic is a BluetoothGattCharacteristic The part where to check the PROPERTY should be like:

if (((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) |
     (charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) > 0) {
 // writing characteristic functions
 mWriteCharacteristic = characteristic;
  }

And, to write your characteristic:

// "str" is the string or character you want to write
byte[] strBytes = str.getBytes();
byte[] bytes = activity.mWriteCharacteristic.getValue();  
YourActivity.this.mWriteCharacteristic.setValue(bytes);
YourActivity.this.writeCharacteristic(YourActivity.this.mWriteCharacteristic);  

Those are the useful parts of the code that you need to implement precisely.

Refer this github project for an implementation with just a basic demo.

Pararth
  • 8,114
  • 4
  • 34
  • 51
  • 1
    ya thanks. I already found `BluetoothLeGatt` github source code and implemented much of the functionality from that including scanning and connecting. Now will look for `Light_BLE` to match the changes and for better development. – sjain May 02 '14 at 06:21
  • Also want to know that my remote BLE will accept commands like "Start" to start the broadcast, and "Stop" to stop the broadcast from BLE to client. So these commands are what you called characteristic in your code ? – sjain May 02 '14 at 06:30
  • yes, you need to program the BLE also, the start and stop can be "1" and "2" values or any other value that you write from the client, it'l involve an if-else loop on the BLE hw programming side – Pararth May 02 '14 at 06:51
  • What var is the charaProp ? – Billyjoker Jan 22 '18 at 10:30
  • 1
    YourActivity.this.mWriteCharacteristic.setValue(strBytes); – cristianego Nov 26 '18 at 20:05
  • in writing data example this line is superflu: byte[] bytes = activity.mWriteCharacteristic.getValue(); code does not work – Sergii Jan 20 '20 at 23:41
10

A noob-friendly guide to make Android interact with a LED-lamp.

Step 1. Get an tool to scan your BLE device. I used "Bluetooth LE Lab" for Win10, but this one will do it as well: https://play.google.com/store/apps/details?id=com.macdom.ble.blescanner

Step 2. Analyse the behavior of the BLE device by entering data, I recommend to enter hex values.

Step 3. Get the sample of the Android docs. https://github.com/googlesamples/android-BluetoothLeGatt

Step 4. Modify the UUIDs you find in SampleGattAttributes

My config:

    public static String CUSTOM_SERVICE = "0000ffe5-0000-1000-8000-00805f9b34fb";
    public static String CLIENT_CHARACTERISTIC_CONFIG = "0000ffe9-0000-1000-8000-00805f9b34fb";

    private static HashMap<String, String> attributes = new HashMap();

    static {
        attributes.put(CUSTOM_SERVICE, CLIENT_CHARACTERISTIC_CONFIG);
        attributes.put(CLIENT_CHARACTERISTIC_CONFIG, "LED");
    }

enter image description here

Step 5. In BluetoothService.java modify onServicesDiscovered:

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
    if (status == BluetoothGatt.GATT_SUCCESS) {

        for (BluetoothGattService gattService : gatt.getServices()) {
            Log.i(TAG, "onServicesDiscovered: ---------------------");
            Log.i(TAG, "onServicesDiscovered: service=" + gattService.getUuid());
            for (BluetoothGattCharacteristic characteristic : gattService.getCharacteristics()) {
                Log.i(TAG, "onServicesDiscovered: characteristic=" + characteristic.getUuid());

                if (characteristic.getUuid().toString().equals("0000ffe9-0000-1000-8000-00805f9b34fb")) {

                    Log.w(TAG, "onServicesDiscovered: found LED");

                    String originalString = "560D0F0600F0AA";

                    byte[] b = hexStringToByteArray(originalString);

                    characteristic.setValue(b); // call this BEFORE(!) you 'write' any stuff to the server
                    mBluetoothGatt.writeCharacteristic(characteristic);

                    Log.i(TAG, "onServicesDiscovered: , write bytes?! " + Utils.byteToHexStr(b));
                }
            }
        }

        broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
    } else {
        Log.w(TAG, "onServicesDiscovered received: " + status);
    }
}

Convert the byte-String using this function:

public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
    data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
            + Character.digit(s.charAt(i + 1), 16));
}
return data;
}

PS: The above code is far away from production, but I hope it helps those, who are new to BLE.

Martin Pfeffer
  • 12,471
  • 9
  • 59
  • 68
  • characteristic.getUuid().toString().equals("0000ffe9-0000-1000-8000-00805f9b34fb") is hardcoded, but i suspect that if you change your BT module by another one, this string would be another different. Maybe some comparition to check if that charasteristic has the write propery would be better – Billyjoker Jan 22 '18 at 10:32