package tmay.bluetoothbacon.ledstrip.services;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import tmay.bluetoothbacon.ledstrip.util.LedstripFrameManager;
import tmay.bluetoothbacon.ledstrip.util.RedBearServiceUUID;
/**
* Created by Terry on 10/5/14.
*/
public class StripControlService extends Service {
public final static String SERVICE_READY = "SERVICE_READY";
public final static String ACTION_GATT_CONNECTED = "ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED = "ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED = "ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_GATT_RSSI = "ACTION_GATT_RSSI";
public final static String ACTION_DATA_AVAILABLE = "ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA = "EXTRA_DATA";
public final static String RAINBOW_WIPE_COMPLETE = "RAINBOW_WIPE_COMPLETE";
public static final String TAG = "strip_control_service";
public class LocalBinder extends Binder {
public StripControlService getService() {
return StripControlService.this;
}
}
private final IBinder binder = new LocalBinder();
private BluetoothGatt gatt;
private BluetoothGattCharacteristic serialTX;
private BluetoothGattCharacteristic serialRX;
private int writeCount = 0;
private boolean isConnected;
private boolean isDisconnecting;
private boolean isRainbowWiping;
private int[] colors;
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public boolean onUnbind(Intent intent) {
//close();
return super.onUnbind(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "Connected to GATT server.");
Log.i(TAG, "Attempting to start service discovery:");
isConnected = true;
gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disco from GATT server.");
close();
isDisconnecting = false;
isConnected = false;
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
serialTX = gatt.getService(RedBearServiceUUID.BLE_SHIELD_SERVICE)
.getCharacteristic(RedBearServiceUUID.BLE_SHIELD_TX);
serialRX = gatt.getService(RedBearServiceUUID.BLE_SHIELD_SERVICE)
.getCharacteristic(RedBearServiceUUID.BLE_SHIELD_RX);
gatt.setCharacteristicNotification(serialRX, true);
BluetoothGattDescriptor descriptor = serialRX.getDescriptor(RedBearServiceUUID.CLIENT_CHARACTERISTIC_CONFIG);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
byte[] b = characteristic.getValue();
for (byte a:b) {
Log.i("incoming byte", a+"");
}
if (b[0] == 49 && writeCount > 0 && colors != null) {
writeCount--;
setPixel(writeCount, colors[writeCount]);
} else if (b[0] == 50 && isDisconnecting) {
gatt.disconnect();
} else if (b[0] == 50 && isRainbowWiping) {
isRainbowWiping = false;
sendBroadcast(new Intent(RAINBOW_WIPE_COMPLETE));
}
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorRead(gatt, descriptor, status);
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
sendBroadcast(new Intent(ACTION_GATT_SERVICES_DISCOVERED));
}
@Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
super.onReliableWriteCompleted(gatt, status);
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
}
};
public void connectGatt(BluetoothDevice device) {
gatt = device.connectGatt(this, true, gattCallback);
}
public void disconnectGatt() {
isDisconnecting = true;
fillStrip(0);
}
public void initStrip(int[] colors) {
this.colors = colors;
writeCount = colors.length-1;
setPixel(writeCount, colors[writeCount]);
}
public void setPixel(int position, int color) {
if (!isConnected)
return;
byte[] pixel = {((byte)position), ((byte)color)};
serialTX.setValue(LedstripFrameManager.buildMessageFrame(pixel));
gatt.writeCharacteristic(serialTX);
}
public void doRainbowWipe() {
if (!isConnected)
return;
isRainbowWiping = true;
byte[] command = {0x65, 0};
serialTX.setValue(LedstripFrameManager.buildMessageFrame(command));
gatt.writeCharacteristic(serialTX);
}
public void fillStrip(int color) {
if (!isConnected)
return;
byte[] command = {0x64, ((byte) color)};
serialTX.setValue(LedstripFrameManager.buildMessageFrame(command));
gatt.writeCharacteristic(serialTX);
}
private void close() {
if (gatt == null) return;
gatt.close();
gatt = null;
}
}