package no.nordicsemi.puckcentral.bluetooth.gatt; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.Context; import org.droidparts.concurrent.task.SimpleAsyncTask; import org.droidparts.util.L; import java.util.ArrayList; import java.util.List; import no.nordicsemi.puckcentral.bluetooth.gatt.operations.GattSetNotificationOperation; import no.nordicsemi.puckcentral.models.Puck; import no.nordicsemi.puckcentral.services.GattServices; import no.nordicsemi.puckcentral.triggers.Trigger; public class CubeConnectionManager { private final Context mCtx; private List<Puck> mConnectedCubes; GattManager mGattManager; public CubeConnectionManager(Context ctx, GattManager gattManager) { mConnectedCubes = new ArrayList<>(); mGattManager = gattManager; mCtx = ctx; L.e("Binding characteristic change listener for cube rotates"); mGattManager.addCharacteristicChangeListener( GattServices.CUBE_CHARACTERISTIC_DIRECTION_UUID, new CharacteristicChangeListener() { @Override public void onCharacteristicChanged(String deviceAddress, BluetoothGattCharacteristic characteristic) { Puck cube = null; for (Puck puck : mConnectedCubes) { if (puck.getAddress().equals(deviceAddress)) { cube = puck; break; } } if (cube == null) { return; } int orientation = characteristic.getValue()[0]; L.e("Rotated cube to " + orientation); final int UP = 0; final int DOWN = 1; final int LEFT = 2; final int RIGHT = 3; final int FRONT = 4; final int BACK = 5; switch (orientation) { case UP: Trigger.trigger(cube, Trigger.TRIGGER_ROTATE_CUBE_UP); break; case DOWN: Trigger.trigger(cube, Trigger.TRIGGER_ROTATE_CUBE_DOWN); break; case LEFT: Trigger.trigger(cube, Trigger.TRIGGER_ROTATE_CUBE_LEFT); break; case RIGHT: Trigger.trigger(cube, Trigger.TRIGGER_ROTATE_CUBE_RIGHT); break; case FRONT: Trigger.trigger(cube, Trigger.TRIGGER_ROTATE_CUBE_FRONT); break; case BACK: Trigger.trigger(cube, Trigger.TRIGGER_ROTATE_CUBE_BACK); break; } } }); } public synchronized void checkAndConnectToPuck(final Puck puck) { if (mConnectedCubes.contains(puck) || !puck.getServiceUUIDs().contains(GattServices.CUBE_SERVICE_UUID)) { return; } L.i("Found Cube Puck. Initiating gatt subscribe to " + puck); mConnectedCubes.add(puck); new SimpleAsyncTask<Void>(mCtx, null) { @Override protected Void onExecute() throws Exception { BluetoothAdapter adapter = ((BluetoothManager) mCtx.getSystemService (Context.BLUETOOTH_SERVICE)).getAdapter(); BluetoothDevice device = adapter.getRemoteDevice(puck.getAddress()); mGattManager.queue(new GattSetNotificationOperation( device, GattServices.CUBE_SERVICE_UUID, GattServices.CUBE_CHARACTERISTIC_DIRECTION_UUID, GattServices.CHARACTERISTIC_UPDATE_NOTIFICATION_DESCRIPTOR_UUID)); // Android BLE stack might have issues connecting to // multiple Gatt services right after another. // See: http://stackoverflow.com/questions/21237093/android-4-3-how-to-connect-to-multiple-bluetooth-low-energy-devices Thread.sleep(1000); return null; } }.execute(); } public void connectionStateChanged(GattManager.ConnectionStateChangedBundle bundle) { for (Puck puck : mConnectedCubes) { if (puck.getAddress().equals(bundle.mAddress)) { if (bundle.mNewState == BluetoothProfile.STATE_DISCONNECTED || bundle.mNewState == 133) { L.i("Disconnected from " + bundle.mAddress + ". Removing from subscribed list."); mConnectedCubes.remove(puck); } } } } }