package io.trygvis.android.bt;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import java.util.Date;
import static io.trygvis.android.bt.BtPromise.PromiseResult.detour;
import static io.trygvis.android.bt.BtPromise.PromiseResult.stop;
public class BtDevice> {
private final static String TAG = BtDevice.class.getSimpleName();
private final DefaultBtService btService;
private final BluetoothDevice bluetoothDevice;
private BluetoothGatt gatt;
private Integer rssi;
private BtScanResult scanResult;
private A tag;
private final long id;
private final boolean seenBefore;
private final Date firstSeen;
private Date lastSeen;
private boolean connected;
private final WrappingBluetoothGattCallback wrappingCallback = new WrappingBluetoothGattCallback();
public static interface BtDeviceWrapper> {
BtDevice getBtDevice();
}
BtDevice(DefaultBtService btService, BluetoothDevice bluetoothDevice, SQLiteDatabase db,
BtService.BtDbIntegration btDbIntegration, long id, Integer rssi,
BtScanResult scanResult, boolean seenBefore, Date firstSeen, Date lastSeen) {
this.btService = btService;
this.bluetoothDevice = bluetoothDevice;
this.id = id;
this.rssi = rssi;
this.scanResult = scanResult;
this.seenBefore = seenBefore;
this.firstSeen = firstSeen;
this.lastSeen = lastSeen;
this.tag = btDbIntegration.createTag(db, this);
}
public long getId() {
return id;
}
public A getTag() {
return tag;
}
public String getAddress() {
return bluetoothDevice.getAddress();
}
public String getName() {
return bluetoothDevice.getName();
}
public int getRssi() {
return rssi;
}
public BtScanResult getScanResult() {
return scanResult;
}
public boolean isSeenBefore() {
return seenBefore;
}
public Date getFirstSeen() {
return firstSeen;
}
public Date getLastSeen() {
return lastSeen;
}
public void setLastSeen(Date lastSeen) {
this.lastSeen = lastSeen;
}
// public synchronized boolean connect(BtPromise executor) {
// Log.i(TAG, "connect(), address=" + bluetoothDevice.getAddress());
// BluetoothGattCallback callback = executor.asCallback(bluetoothDevice.getAddress());
// gatt = bluetoothDevice.connectGatt(btService, false, new WrappingBluetoothGattCallback(callback) {
// @Override
// public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
// BtDevice.this.connected = newState == BluetoothGatt.STATE_CONNECTED;
//
// super.onConnectionStateChange(gatt, status, newState);
// }
// });
// return true;
// }
private BluetoothGattCallback callback;
public synchronized void withConnection(BtPromise promise) {
if (callback != null) {
throw new RuntimeException("The current callback is not done.");
}
Log.i(TAG, "withConnection(), address=" + bluetoothDevice.getAddress() + ", connected: " + (gatt != null));
if (gatt == null) {
callback = new BtPromise().
ignoreFailureForNext().
onConnectionStateChange((gatt, status, newState) -> {
Log.i(TAG, "defaultConnectCallback: status=" + status + ", newState=" + newState);
String address = gatt.getDevice().getAddress();
//noinspection SimplifiableIfStatement
if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothGatt.STATE_CONNECTED) {
Log.i(TAG, "Connected to " + address);
return detour(promise);
} else {
Log.i(TAG, "Could not connect to " + address + ", trying again");
return detour(new BtPromise().onConnectionStateChange((gatt2, status2, newState2) -> {
if (status2 == BluetoothGatt.GATT_SUCCESS && newState2 == BluetoothGatt.STATE_CONNECTED) {
Log.i(TAG, "Connected to " + address);
return detour(promise);
}
Log.i(TAG, "Could still not connect to " + address + ", failing.");
return stop();
}));
}
}).
asCallback(bluetoothDevice.getAddress());
} else {
callback = promise.asCallback(bluetoothDevice.getAddress());
}
gatt = bluetoothDevice.connectGatt(btService, false, wrappingCallback);
}
// public synchronized void disconnect() {
// if (gatt != null) {
// gatt.disconnect();
// gatt = null;
// }
// }
public boolean connected() {
return connected;
}
@Override
public String toString() {
return "BtDevice{address=" + bluetoothDevice.getAddress() + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
BtDevice other = (BtDevice) o;
return getAddress().equals(other.getAddress());
}
@Override
public int hashCode() {
return getAddress().hashCode();
}
private class WrappingBluetoothGattCallback extends BluetoothGattCallback {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
BtDevice.this.connected = newState == BluetoothGatt.STATE_CONNECTED;
if (callback != null) {
callback.onConnectionStateChange(gatt, status, newState);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (callback != null) {
callback.onServicesDiscovered(gatt, status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (callback != null) {
callback.onCharacteristicRead(gatt, characteristic, status);
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (callback != null) {
callback.onCharacteristicWrite(gatt, characteristic, status);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
if (callback != null) {
callback.onCharacteristicChanged(gatt, characteristic);
}
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
if (callback != null) {
callback.onDescriptorRead(gatt, descriptor, status);
}
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
if (callback != null) {
callback.onDescriptorWrite(gatt, descriptor, status);
}
}
@Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
if (callback != null) {
callback.onReliableWriteCompleted(gatt, status);
}
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
if (callback != null) {
callback.onReadRemoteRssi(gatt, rssi, status);
}
}
}
}