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);
}
}
}
}
}