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