I've made significant progress with this activity. I'm now able to communicate with the CBT's UART. This updated example discovers the CBT, connects to it, subscribes to its notification characteristic, sends an 0x01 0x01 command, reads the response, and then sets the BT filter (0x04 0x01 0x0028 0x0028) for a known good register and filter value I use over USB (0x03 0x01 0x01 0x0028 0x0028).
Unfortunately I never receive anything beyond the initial status response. I have the exact same results using LightBlue for OS X.
<pre><code>package com.shellware.genesisconnect;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends Activity {
private final static UUID CLIENT_CHARACTERISTIC_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
private final static UUID BLE_SERVICE_UUID = UUID.fromString("7a1fb359-735c-4983-8082-bdd7674c74d2");
private final static UUID RECEIVE_NOTIFY_CHARACTERISTIC_UUID = UUID.fromString("B0D6C9FE-E38A-4D31-9272-B8B3E93D8658");
private final static UUID RECEIVE_INDICATE_CHARACTERISTIC_UUID = UUID.fromString("B0D6C9FE-E38A-4D31-9272-B8B3E93D8657");
private Context context;
boolean filterSet = false;
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private BluetoothDevice bluetoothDevice;
private BluetoothGatt bluetoothGatt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, 1);
} else {
if (bluetoothAdapter == null) {
Toast.makeText(context, "No Bluetooth adapter found", Toast.LENGTH_SHORT).show();
} else {
final boolean stat = bluetoothAdapter.startLeScan(leScanCallback);
Toast.makeText(context, String.format("Boothtooth LE Scan Started - %b", stat), Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected void onPause() {
super.onPause();
if (bluetoothAdapter != null && bluetoothAdapter.isEnabled()) {
Toast.makeText(context, "Stopping LE Scan", Toast.LENGTH_SHORT).show();
bluetoothAdapter.stopLeScan(leScanCallback);
if (bluetoothGatt != null) {
Toast.makeText(context, "Disconnecting GATT", Toast.LENGTH_SHORT).show();
bluetoothGatt.disconnect();
Toast.makeText(context, "Closing GATT", Toast.LENGTH_SHORT).show();
bluetoothGatt.close();
}
}
}
private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
if (device.getName().contains("CANBus Triple")) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, String.format("Found %s - %s",device.getName(), device.getAddress()), Toast.LENGTH_SHORT).show();
}
});
bluetoothDevice = device;
bluetoothAdapter.stopLeScan(leScanCallback);
bluetoothGatt = bluetoothDevice.connectGatt(context, false, btleGattCallback);
}
}
};
private final BluetoothGattCallback btleGattCallback = new BluetoothGattCallback() {
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, new String(characteristic.getValue()), Toast.LENGTH_SHORT).show();
}});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (!filterSet) {
// look for stereo DISP button press
byte[] msg = {0x04, 0x01, 0x0028, 0x0028};
characteristic.setValue(msg);
bluetoothGatt.writeCharacteristic(characteristic);
filterSet = true;
}
}
@Override
public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, "Connected!", Toast.LENGTH_SHORT).show();
}
});
bluetoothGatt.discoverServices();
}
}
@Override
public void onServicesDiscovered(final BluetoothGatt gatt, final int status) {
super.onServicesDiscovered(gatt, status);
BluetoothGattService service = bluetoothGatt.getService(BLE_SERVICE_UUID);
if (service == null) return;
BluetoothGattCharacteristic notifyCharacteristic = service.getCharacteristic(RECEIVE_NOTIFY_CHARACTERISTIC_UUID);
// BluetoothGattCharacteristic indicateCharacteristic = service.getCharacteristic(RECEIVE_INDICATE_CHARACTERISTIC_UUID);
BluetoothGattDescriptor notifyDescriptor = notifyCharacteristic.getDescriptor(CLIENT_CHARACTERISTIC_UUID);
// BluetoothGattDescriptor indicateDescriptor = indicateCharacteristic.getDescriptor(CLIENT_CHARACTERISTIC_UUID);
bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true);
notifyDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(notifyDescriptor);
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
byte[] msg = {0x01, 0x01};
descriptor.getCharacteristic().setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
descriptor.getCharacteristic().setValue(msg);
bluetoothGatt.writeCharacteristic(descriptor.getCharacteristic());
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, "Service configured", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, "Wrote to Characteristic", Toast.LENGTH_SHORT).show();
}
});
}
};
}</code></pre>