From 1ca69ec414d32e6f71aaa31df3361e2727a32c1c Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Wed, 24 Feb 2021 11:49:24 +0100 Subject: [PATCH 1/6] Ble updates - stop Thread.sleep()ing and use CountDownLatches for connection and service discovery state - prepare BleIO for reading/writing - define CharacteristicType for the CMD/DATA characteristics - prepare BlePacket for DATA packets(the equivalent of BleCommand) --- .../dash/driver/comm/BleCommCallbacks.java | 48 ++++++++ .../pump/omnipod/dash/driver/comm/BleIO.java | 76 ++++++++++++ .../omnipod/dash/driver/comm/BleManager.java | 113 +++++------------- .../dash/driver/comm/CharacteristicType.java | 35 ++++++ .../dash/driver/comm/ServiceDiscoverer.java | 74 ++++++++++++ .../{blecommand => command}/BleCommand.java | 2 +- .../BleCommandHello.java | 2 +- .../BleCommandType.java | 2 +- .../CouldNotSendBleCmdException.java | 4 - .../exceptions/CouldNotSendBleException.java | 3 + .../dash/driver/comm/packet/BlePacket.java | 4 + 11 files changed, 276 insertions(+), 87 deletions(-) create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleIO.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java rename omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/{blecommand => command}/BleCommand.java (96%) rename omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/{blecommand => command}/BleCommandHello.java (95%) rename omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/{blecommand => command}/BleCommandType.java (97%) delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleCmdException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/packet/BlePacket.java diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleCommCallbacks.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleCommCallbacks.java index 235cd5434d6..aa8044266fc 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleCommCallbacks.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleCommCallbacks.java @@ -1,7 +1,55 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm; +import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothProfile; + +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.logging.LTag; public class BleCommCallbacks extends BluetoothGattCallback { + private final CountDownLatch serviceDiscoveryComplete; + private final CountDownLatch connected; + private final AAPSLogger aapsLogger; + private final Map> incomingPackets; + + public BleCommCallbacks(AAPSLogger aapsLogger, Map> incomingPackets) { + this.serviceDiscoveryComplete = new CountDownLatch(1); + this.connected = new CountDownLatch(1); + this.aapsLogger = aapsLogger; + this.incomingPackets = incomingPackets; + } + + + @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { + super.onConnectionStateChange(gatt, status, newState); + this.aapsLogger.debug(LTag.PUMPBTCOMM,"OnConnectionStateChange discovered with status/state"+status+"/"+newState); + if (newState == BluetoothProfile.STATE_CONNECTED && status == BluetoothGatt.GATT_SUCCESS) { + this.connected.countDown(); + } + } + + @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { + super.onServicesDiscovered(gatt, status); + this.aapsLogger.debug(LTag.PUMPBTCOMM,"OnServicesDiscovered with status"+status); + if (status == gatt.GATT_SUCCESS) { + this.serviceDiscoveryComplete.countDown(); + } + } + + public void waitForConnection(int timeout_ms) + throws InterruptedException { + this.connected.await(timeout_ms, TimeUnit.MILLISECONDS); + } + + public void waitForServiceDiscovery(int timeout_ms) + throws InterruptedException { + this.serviceDiscoveryComplete.await(timeout_ms, TimeUnit.MILLISECONDS); + } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleIO.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleIO.java new file mode 100644 index 00000000000..40c76d5de26 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleIO.java @@ -0,0 +1,76 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; + +import java.util.Map; +import java.util.concurrent.BlockingQueue; + +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.logging.LTag; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotSendBleException; + + +public class BleIO { + private static final int DEFAULT_IO_TIMEOUT_MS = 1000; + + private final AAPSLogger aapsLogger; + private final Map chars; + private final Map> incomingPackets; + private final BluetoothGatt gatt; + + + public BleIO(AAPSLogger aapsLogger, Map chars, Map> incomingPackets, BluetoothGatt gatt) { + this.aapsLogger = aapsLogger; + this.chars = chars; + this.incomingPackets = incomingPackets; + this.gatt = gatt; + } + + /*** + * + * @param characteristic where to read from(CMD or DATA) + * @return a byte array with the received data + */ + public byte[] receiveData(CharacteristicType characteristic) { + return null; + } + + /*** + * + * @param characteristic where to write to(CMD or DATA) + * @param packet the data to send + * @throws CouldNotSendBleException + */ + public void sendAndConfirmData(CharacteristicType characteristic, byte[] packet) + throws CouldNotSendBleException { + aapsLogger.debug(LTag.PUMPBTCOMM, "BleIO: Sending data on " + characteristic.name() + " :: " +packet.toString()); + BluetoothGattCharacteristic ch = chars.get(characteristic); + boolean set = ch.setValue(packet); + if (!set) { + throw new CouldNotSendBleException("setValue"); + } + boolean sent = this.gatt.writeCharacteristic(ch); + if (!sent) { + throw new CouldNotSendBleException("writeCharacteristic"); + } + // TODO: wait for confirmation callback + } + + /** + * Called before sending a new message. + * The incoming queues should be empty, so we log when they are not. + */ + public void flushIncomingQueues() { + + } + + /** + * Enable intentions on the characteristics. + * This will signal the pod it can start sending back data + */ + public void readyToRead() + throws CouldNotSendBleException { + + } +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java index c8a14ed3366..fdacd4e3951 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java @@ -3,40 +3,34 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.Context; -import java.math.BigInteger; -import java.util.UUID; +import java.util.Collections; +import java.util.EnumMap; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; import javax.inject.Inject; import javax.inject.Singleton; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.blecommand.BleCommand; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.blecommand.BleCommandHello; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.blecommand.BleCommandType; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CharacteristicNotFoundException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotSendBleCmdException; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.BuildConfig; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.BleCommandHello; import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotSendBleException; import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.FailedToConnectException; import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ServiceNotFoundException; import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.PodScanner; @Singleton public class BleManager implements OmnipodDashCommunicationManager { private static final int CONNECT_TIMEOUT_MS = 5000; - private static final int DISCOVER_SERVICES_TIMEOUT_MS = 5000; - private static final String SERVICE_UUID = "1a7e-4024-e3ed-4464-8b7e-751e03d0dc5f"; - private static final String CMD_CHARACTERISTIC_UUID = "1a7e-2441-e3ed-4464-8b7e-751e03d0dc5f"; - private static final String DATA_CHARACTERISTIC_UUID = "1a7e-2442-e3ed-4464-8b7e-751e03d0dc5f"; private static final int CONTROLLER_ID = 4242; // TODO read from preferences or somewhere else. + private static BleManager instance = null; private final Context context; private final BluetoothAdapter bluetoothAdapter; @@ -44,9 +38,7 @@ public class BleManager implements OmnipodDashCommunicationManager { @Inject AAPSLogger aapsLogger; private String podAddress; private BluetoothGatt gatt; - - private BluetoothGattCharacteristic cmdCharacteristic; - private BluetoothGattCharacteristic dataCharacteristic; + private BleIO bleio; @Inject public BleManager(Context context) { @@ -66,13 +58,6 @@ public static BleManager getInstance(Context context) { return ret; } - private static UUID uuidFromString(String s) { - return new UUID( - new BigInteger(s.replace("-", "").substring(0, 16), 16).longValue(), - new BigInteger(s.replace("-", "").substring(16), 16).longValue() - ); - } - public void activateNewPod() throws InterruptedException, ScanFailException, @@ -82,78 +67,46 @@ public void activateNewPod() PodScanner podScanner = new PodScanner(this.aapsLogger, this.bluetoothAdapter); this.podAddress = podScanner.scanForPod(PodScanner.SCAN_FOR_SERVICE_UUID, PodScanner.POD_ID_NOT_ACTIVATED).getScanResult().getDevice().getAddress(); // For tests: this.podAddress = "B8:27:EB:1D:7E:BB"; - this.connect(); - // do the dance: send SP0, SP1, etc - // get and save LTK + this.connect_(); } - public void connect() + public void connect_() throws FailedToConnectException, - CouldNotSendBleException { + CouldNotSendBleException, + InterruptedException { // TODO: locking? BluetoothDevice podDevice = this.bluetoothAdapter.getRemoteDevice(this.podAddress); - BluetoothGattCallback bleCommCallback = new BleCommCallbacks(); - aapsLogger.debug(LTag.PUMPBTCOMM, "Connecting to " + this.podAddress); - gatt = podDevice.connectGatt(this.context, true, bleCommCallback, BluetoothDevice.TRANSPORT_LE); + Map> incomingPackets = new EnumMap>(CharacteristicType.class); + incomingPackets.put(CharacteristicType.CMD, new LinkedBlockingDeque<>()); + incomingPackets.put(CharacteristicType.DATA, new LinkedBlockingDeque<>()); + incomingPackets = Collections.unmodifiableMap(incomingPackets); - try { - Thread.sleep(CONNECT_TIMEOUT_MS); - } catch (InterruptedException e) { - // we get interrupted on successful connection - // TODO: interrupt this thread onConnect() + BleCommCallbacks bleCommCallbacks = new BleCommCallbacks(aapsLogger, incomingPackets); + + aapsLogger.debug(LTag.PUMPBTCOMM, "Connecting to " + this.podAddress); + boolean autoConnect = true; + if (BuildConfig.DEBUG) { + autoConnect = false; + // TODO: remove this in the future + // it's easier to start testing from scratch on each run. } + gatt = podDevice.connectGatt(this.context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE); + + bleCommCallbacks.waitForConnection(CONNECT_TIMEOUT_MS); int connectionState = this.bluetoothManager.getConnectionState(podDevice, BluetoothProfile.GATT); aapsLogger.debug(LTag.PUMPBTCOMM, "GATT connection state: " + connectionState); if (connectionState != BluetoothProfile.STATE_CONNECTED) { throw new FailedToConnectException(this.podAddress); } - this.discoverServicesAndSayHello(gatt); - - } - - private void discoverServicesAndSayHello(BluetoothGatt gatt) - throws FailedToConnectException, - CouldNotSendBleException { - gatt.discoverServices(); - try { - Thread.sleep(CONNECT_TIMEOUT_MS); - } catch (InterruptedException e) { - // we get interrupted on successfull connection - // TODO: interrupt this thread onConnect() - } - - BluetoothGattService service = gatt.getService(uuidFromString(SERVICE_UUID)); - if (service == null) { - throw new ServiceNotFoundException(SERVICE_UUID); - } - BluetoothGattCharacteristic cmdChar = service.getCharacteristic(uuidFromString(CMD_CHARACTERISTIC_UUID)); - if (cmdChar == null) { - throw new CharacteristicNotFoundException(CMD_CHARACTERISTIC_UUID); - } - BluetoothGattCharacteristic dataChar = service.getCharacteristic(uuidFromString(DATA_CHARACTERISTIC_UUID)); - if (dataChar == null) { - throw new CharacteristicNotFoundException(DATA_CHARACTERISTIC_UUID); - } - this.cmdCharacteristic = cmdChar; - this.dataCharacteristic = dataChar; - - BleCommand hello = new BleCommandHello(CONTROLLER_ID); - if (!this.sendCmd(hello.asByteArray())) { - throw new CouldNotSendBleCmdException(); - } - aapsLogger.debug(LTag.PUMPBTCOMM, "saying hello to the pod" + hello.asByteArray()); - } + ServiceDiscoverer discoverer = new ServiceDiscoverer(this.aapsLogger, gatt, bleCommCallbacks); + Map chars = discoverer.discoverServices(); - private boolean sendCmd(byte[] payload) { - // TODO move out of here - this.cmdCharacteristic.setValue(payload); - boolean ret = this.gatt.writeCharacteristic(cmdCharacteristic); - aapsLogger.debug(LTag.PUMPBTCOMM, "Sending command status. data:" + payload.toString() + "status: " + ret); - return ret; + this.bleio = new BleIO(aapsLogger, chars, incomingPackets, gatt); + this.aapsLogger.debug(LTag.PUMPBTCOMM, "Saying hello to the pod"); + this.bleio.sendAndConfirmData(CharacteristicType.CMD, new BleCommandHello(CONTROLLER_ID).asByteArray()); } } - diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java new file mode 100644 index 00000000000..cdc4bdb46ba --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java @@ -0,0 +1,35 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm; + +import java.math.BigInteger; +import java.util.UUID; + +public enum CharacteristicType { + CMD("1a7e-2441-e3ed-4464-8b7e-751e03d0dc5f"), + DATA("1a7e-2442-e3ed-4464-8b7e-751e03d0dc5f"); + + public final String value; + + CharacteristicType(String value) { + this.value = value; + } + + public static CharacteristicType byValue(byte value) { + for (CharacteristicType type : values()) { + if (type.value.equals(value)) { + return type; + } + } + throw new IllegalArgumentException("Unknown Characteristic Type: " + value); + } + + public String getValue() { + return this.value; + } + + public UUID getUUID() { + return new UUID( + new BigInteger(this.value.replace("-", "").substring(0, 16), 16).longValue(), + new BigInteger(this.value.replace("-", "").substring(16), 16).longValue() + ); + } +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java new file mode 100644 index 00000000000..c30cfce8e97 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java @@ -0,0 +1,74 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattService; + +import java.math.BigInteger; +import java.util.Collections; +import java.util.EnumMap; +import java.util.Map; +import java.util.UUID; + +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.logging.LTag; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CharacteristicNotFoundException; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ServiceNotFoundException; + +public class ServiceDiscoverer { + private static final String SERVICE_UUID = "1a7e-4024-e3ed-4464-8b7e-751e03d0dc5f"; + private static final int DISCOVER_SERVICES_TIMEOUT_MS = 5000; + + private final BluetoothGatt gatt; + private final BleCommCallbacks bleCallbacks; + private final AAPSLogger logger; + private Map chars; + + public ServiceDiscoverer(AAPSLogger logger, BluetoothGatt gatt, BleCommCallbacks bleCallbacks) { + this.gatt = gatt; + this.bleCallbacks = bleCallbacks; + this.logger = logger; + } + + private static UUID uuidFromString(String s) { + return new UUID( + new BigInteger(s.replace("-", "").substring(0, 16), 16).longValue(), + new BigInteger(s.replace("-", "").substring(16), 16).longValue() + ); + } + + /*** + * This is first step after connection establishment + */ + public Map discoverServices() + throws InterruptedException, + ServiceNotFoundException, + CharacteristicNotFoundException { + + logger.debug(LTag.PUMPBTCOMM, "Discovering services"); + gatt.discoverServices(); + this.bleCallbacks.waitForServiceDiscovery(DISCOVER_SERVICES_TIMEOUT_MS); + logger.debug(LTag.PUMPBTCOMM, "Services discovered"); + + BluetoothGattService service = gatt.getService( + uuidFromString(SERVICE_UUID)); + if (service == null) { + throw new ServiceNotFoundException(SERVICE_UUID); + } + BluetoothGattCharacteristic cmdChar = service.getCharacteristic(CharacteristicType.CMD.getUUID()); + if (cmdChar == null) { + throw new CharacteristicNotFoundException(CharacteristicType.CMD.getValue()); + } + BluetoothGattCharacteristic dataChar = service.getCharacteristic(CharacteristicType.DATA.getUUID()); + if (dataChar == null) { + throw new CharacteristicNotFoundException(CharacteristicType.DATA.getValue()); + } + Map chars = new EnumMap(CharacteristicType.class); + chars.put(CharacteristicType.CMD, cmdChar); + chars.put(CharacteristicType.DATA, dataChar); + this.chars = Collections.unmodifiableMap(chars); + return this.chars; + } + +} + diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/blecommand/BleCommand.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.java similarity index 96% rename from omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/blecommand/BleCommand.java rename to omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.java index 86cd356ff37..4af111d6337 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/blecommand/BleCommand.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.blecommand; +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command; import org.jetbrains.annotations.NotNull; diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/blecommand/BleCommandHello.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandHello.java similarity index 95% rename from omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/blecommand/BleCommandHello.java rename to omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandHello.java index 3bcabacc28b..56659f45e5c 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/blecommand/BleCommandHello.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandHello.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.blecommand; +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command; import java.nio.ByteBuffer; diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/blecommand/BleCommandType.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.java similarity index 97% rename from omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/blecommand/BleCommandType.java rename to omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.java index 4bd71a357de..38225bf799c 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/blecommand/BleCommandType.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.java @@ -1,4 +1,4 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.blecommand; +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command; public enum BleCommandType { RTS((byte) 0x00), diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleCmdException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleCmdException.java deleted file mode 100644 index ae2d1e4be46..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleCmdException.java +++ /dev/null @@ -1,4 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -public class CouldNotSendBleCmdException extends CouldNotSendBleException { -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.java index 8bca9c732d1..6bd30f5ff82 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.java @@ -1,4 +1,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; public class CouldNotSendBleException extends Exception { + public CouldNotSendBleException(String msg) { + super(msg); + } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/packet/BlePacket.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/packet/BlePacket.java new file mode 100644 index 00000000000..54babad0499 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/packet/BlePacket.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet; + +public class BlePacket { +} From b4d769844c61aae8744afe5111c34b865f18c6f6 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Wed, 24 Feb 2021 13:00:08 +0100 Subject: [PATCH 2/6] ble-io: implement confirmation for writes and make sure there is only one one IO operation in progress. In theory, we could have parallel IO operations on each characteristic, but I'm not sure yet if we really need to support that. implement reads enable notifications. Use BlockingQueue for write confirmations --- .../dash/driver/comm/BleCommCallbacks.java | 55 ------- .../pump/omnipod/dash/driver/comm/BleIO.java | 76 --------- .../omnipod/dash/driver/comm/BleManager.java | 25 ++- .../dash/driver/comm/CharacteristicType.java | 6 +- .../dash/driver/comm/ServiceDiscoverer.java | 1 + .../comm/callbacks/BleCommCallbacks.java | 147 ++++++++++++++++++ .../CharacteristicWriteConfirmation.java | 11 ++ .../DescriptorWriteConfirmation.java | 11 ++ .../comm/exceptions/BleIOBusyException.java | 4 + ...uldNotConfirmDescriptorWriteException.java | 12 ++ .../comm/exceptions/CouldNotConfirmWrite.java | 13 ++ .../CouldNotEnableNotifications.java | 9 ++ .../DescriptorNotFoundException.java | 4 + .../omnipod/dash/driver/comm/io/BleIO.java | 140 +++++++++++++++++ .../omnipod/dash/driver/comm/io/IOState.java | 7 + 15 files changed, 381 insertions(+), 140 deletions(-) delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleCommCallbacks.java delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleIO.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.java diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleCommCallbacks.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleCommCallbacks.java deleted file mode 100644 index aa8044266fc..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleCommCallbacks.java +++ /dev/null @@ -1,55 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCallback; -import android.bluetooth.BluetoothProfile; - -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; - -public class BleCommCallbacks extends BluetoothGattCallback { - private final CountDownLatch serviceDiscoveryComplete; - private final CountDownLatch connected; - private final AAPSLogger aapsLogger; - private final Map> incomingPackets; - - public BleCommCallbacks(AAPSLogger aapsLogger, Map> incomingPackets) { - this.serviceDiscoveryComplete = new CountDownLatch(1); - this.connected = new CountDownLatch(1); - this.aapsLogger = aapsLogger; - this.incomingPackets = incomingPackets; - } - - - @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - super.onConnectionStateChange(gatt, status, newState); - this.aapsLogger.debug(LTag.PUMPBTCOMM,"OnConnectionStateChange discovered with status/state"+status+"/"+newState); - if (newState == BluetoothProfile.STATE_CONNECTED && status == BluetoothGatt.GATT_SUCCESS) { - this.connected.countDown(); - } - } - - @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { - super.onServicesDiscovered(gatt, status); - this.aapsLogger.debug(LTag.PUMPBTCOMM,"OnServicesDiscovered with status"+status); - if (status == gatt.GATT_SUCCESS) { - this.serviceDiscoveryComplete.countDown(); - } - } - - public void waitForConnection(int timeout_ms) - throws InterruptedException { - this.connected.await(timeout_ms, TimeUnit.MILLISECONDS); - } - - public void waitForServiceDiscovery(int timeout_ms) - throws InterruptedException { - this.serviceDiscoveryComplete.await(timeout_ms, TimeUnit.MILLISECONDS); - } - -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleIO.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleIO.java deleted file mode 100644 index 40c76d5de26..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleIO.java +++ /dev/null @@ -1,76 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCharacteristic; - -import java.util.Map; -import java.util.concurrent.BlockingQueue; - -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotSendBleException; - - -public class BleIO { - private static final int DEFAULT_IO_TIMEOUT_MS = 1000; - - private final AAPSLogger aapsLogger; - private final Map chars; - private final Map> incomingPackets; - private final BluetoothGatt gatt; - - - public BleIO(AAPSLogger aapsLogger, Map chars, Map> incomingPackets, BluetoothGatt gatt) { - this.aapsLogger = aapsLogger; - this.chars = chars; - this.incomingPackets = incomingPackets; - this.gatt = gatt; - } - - /*** - * - * @param characteristic where to read from(CMD or DATA) - * @return a byte array with the received data - */ - public byte[] receiveData(CharacteristicType characteristic) { - return null; - } - - /*** - * - * @param characteristic where to write to(CMD or DATA) - * @param packet the data to send - * @throws CouldNotSendBleException - */ - public void sendAndConfirmData(CharacteristicType characteristic, byte[] packet) - throws CouldNotSendBleException { - aapsLogger.debug(LTag.PUMPBTCOMM, "BleIO: Sending data on " + characteristic.name() + " :: " +packet.toString()); - BluetoothGattCharacteristic ch = chars.get(characteristic); - boolean set = ch.setValue(packet); - if (!set) { - throw new CouldNotSendBleException("setValue"); - } - boolean sent = this.gatt.writeCharacteristic(ch); - if (!sent) { - throw new CouldNotSendBleException("writeCharacteristic"); - } - // TODO: wait for confirmation callback - } - - /** - * Called before sending a new message. - * The incoming queues should be empty, so we log when they are not. - */ - public void flushIncomingQueues() { - - } - - /** - * Enable intentions on the characteristics. - * This will signal the pod it can start sending back data - */ - public void readyToRead() - throws CouldNotSendBleException { - - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java index fdacd4e3951..35164c4cc17 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java @@ -13,6 +13,7 @@ import java.util.Map; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.TimeoutException; import javax.inject.Inject; import javax.inject.Singleton; @@ -20,7 +21,14 @@ import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.pump.omnipod.dash.BuildConfig; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks; import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.BleCommandHello; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.BleIOBusyException; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotEnableNotifications; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.DescriptorNotFoundException; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.BleIO; import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotSendBleException; import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.FailedToConnectException; import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailException; @@ -62,18 +70,22 @@ public void activateNewPod() throws InterruptedException, ScanFailException, FailedToConnectException, - CouldNotSendBleException { + CouldNotSendBleException, + BleIOBusyException, + TimeoutException, + CouldNotConfirmWrite, CouldNotEnableNotifications, DescriptorNotFoundException, CouldNotConfirmDescriptorWriteException { this.aapsLogger.info(LTag.PUMPBTCOMM, "starting new pod activation"); PodScanner podScanner = new PodScanner(this.aapsLogger, this.bluetoothAdapter); this.podAddress = podScanner.scanForPod(PodScanner.SCAN_FOR_SERVICE_UUID, PodScanner.POD_ID_NOT_ACTIVATED).getScanResult().getDevice().getAddress(); // For tests: this.podAddress = "B8:27:EB:1D:7E:BB"; - this.connect_(); + this.connect(); } - public void connect_() + public void connect() throws FailedToConnectException, CouldNotSendBleException, - InterruptedException { + InterruptedException, + BleIOBusyException, TimeoutException, CouldNotConfirmWrite, CouldNotEnableNotifications, DescriptorNotFoundException, CouldNotConfirmDescriptorWriteException { // TODO: locking? BluetoothDevice podDevice = this.bluetoothAdapter.getRemoteDevice(this.podAddress); @@ -105,8 +117,9 @@ public void connect_() ServiceDiscoverer discoverer = new ServiceDiscoverer(this.aapsLogger, gatt, bleCommCallbacks); Map chars = discoverer.discoverServices(); - this.bleio = new BleIO(aapsLogger, chars, incomingPackets, gatt); + this.bleio = new BleIO(aapsLogger, chars, incomingPackets, gatt, bleCommCallbacks); this.aapsLogger.debug(LTag.PUMPBTCOMM, "Saying hello to the pod"); - this.bleio.sendAndConfirmData(CharacteristicType.CMD, new BleCommandHello(CONTROLLER_ID).asByteArray()); + this.bleio.sendAndConfirmPacket(CharacteristicType.CMD, new BleCommandHello(CONTROLLER_ID).asByteArray()); + this.bleio.readyToRead(); } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java index cdc4bdb46ba..73bcc9de61d 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java @@ -4,8 +4,8 @@ import java.util.UUID; public enum CharacteristicType { - CMD("1a7e-2441-e3ed-4464-8b7e-751e03d0dc5f"), - DATA("1a7e-2442-e3ed-4464-8b7e-751e03d0dc5f"); + CMD("1a7e2441-e3ed-4464-8b7e-751e03d0dc5f"), + DATA("1a7e2442-e3ed-4464-8b7e-751e03d0dc5f"); public final String value; @@ -13,7 +13,7 @@ public enum CharacteristicType { this.value = value; } - public static CharacteristicType byValue(byte value) { + public static CharacteristicType byValue(String value) { for (CharacteristicType type : values()) { if (type.value.equals(value)) { return type; diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java index c30cfce8e97..13828db4d0a 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java @@ -12,6 +12,7 @@ import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks; import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CharacteristicNotFoundException; import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ServiceNotFoundException; diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.java new file mode 100644 index 00000000000..28a202606e7 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.java @@ -0,0 +1,147 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; +import android.bluetooth.BluetoothProfile; + +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.logging.LTag; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite; + +public class BleCommCallbacks extends BluetoothGattCallback { + private final static int WRITE_CONFIRM_TIMEOUT_MS = 10; // the other thread should be waiting for the exchange + + private final CountDownLatch serviceDiscoveryComplete; + private final CountDownLatch connected; + private final AAPSLogger aapsLogger; + private final Map> incomingPackets; + private final BlockingQueue writeQueue; + private final BlockingQueue descriptorWriteQueue; + + public BleCommCallbacks(AAPSLogger aapsLogger, Map> incomingPackets) { + this.serviceDiscoveryComplete = new CountDownLatch(1); + this.connected = new CountDownLatch(1); + this.aapsLogger = aapsLogger; + this.incomingPackets = incomingPackets; + this.writeQueue = new LinkedBlockingQueue<>(1); + this.descriptorWriteQueue = new LinkedBlockingQueue<>(1); + } + + @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { + super.onConnectionStateChange(gatt, status, newState); + this.aapsLogger.debug(LTag.PUMPBTCOMM, "OnConnectionStateChange discovered with status/state" + status + "/" + newState); + if (newState == BluetoothProfile.STATE_CONNECTED && status == BluetoothGatt.GATT_SUCCESS) { + this.connected.countDown(); + } + } + + @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { + super.onServicesDiscovered(gatt, status); + this.aapsLogger.debug(LTag.PUMPBTCOMM, "OnServicesDiscovered with status" + status); + if (status == BluetoothGatt.GATT_SUCCESS) { + this.serviceDiscoveryComplete.countDown(); + } + } + + public void waitForConnection(int timeout_ms) + throws InterruptedException { + this.connected.await(timeout_ms, TimeUnit.MILLISECONDS); + } + + public void waitForServiceDiscovery(int timeout_ms) + throws InterruptedException { + this.serviceDiscoveryComplete.await(timeout_ms, TimeUnit.MILLISECONDS); + } + + public void confirmWrite(CharacteristicType characteristicType, byte[] expectedPayload, int timeout_ms) throws InterruptedException, TimeoutException, CouldNotConfirmWrite { + CharacteristicWriteConfirmation received = this.writeQueue.poll(timeout_ms, TimeUnit.MILLISECONDS); + if (received == null ) { + throw new TimeoutException(); + } + if (!Arrays.equals(expectedPayload, received.payload)) { + this.aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm write. Got " + received.payload + ".Excepted: " + expectedPayload + ". Status: "+received.status); + throw new CouldNotConfirmWrite(expectedPayload, received.payload); + } + this.aapsLogger.debug(LTag.PUMPBTCOMM, "Confirmed write with value: " + received.payload); + } + + @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + super.onCharacteristicWrite(gatt, characteristic, status); + byte[] received = null; + + if (status == BluetoothGatt.GATT_SUCCESS) { + received = characteristic.getValue(); + this.aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicWrite value " + characteristic.getStringValue(0)); + } + + this.aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicWrite with status/char/value " + + status + "/" + + CharacteristicType.byValue(characteristic.getUuid().toString()) + "/" + + received); + try { + if (this.writeQueue.size() > 0) { + this.aapsLogger.warn(LTag.PUMPBTCOMM, "Write confirm queue should be empty. found: "+ this.writeQueue.size()); + this.writeQueue.clear(); + } + boolean offered = this.writeQueue.offer(new CharacteristicWriteConfirmation(received, status), WRITE_CONFIRM_TIMEOUT_MS, TimeUnit.MILLISECONDS); + if (!offered) { + this.aapsLogger.warn(LTag.PUMPBTCOMM, "Received delayed write confirmation"); + } + } catch (InterruptedException e) { + this.aapsLogger.warn(LTag.PUMPBTCOMM, "Interrupted while sending write confirmation"); + } + } + + @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + super.onCharacteristicChanged(gatt, characteristic); + + byte[] payload = characteristic.getValue(); + CharacteristicType characteristicType = CharacteristicType.byValue(characteristic.getUuid().toString()); + this.aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicChanged with char/value " + + characteristicType + "/" + + payload); + this.incomingPackets.get(characteristicType).add(payload); + } + + public void confirmWriteDescriptor(String descriptorUUID, int timeout_ms) throws InterruptedException, CouldNotConfirmDescriptorWriteException { + DescriptorWriteConfirmation confirmed = this.descriptorWriteQueue.poll(timeout_ms, TimeUnit.MILLISECONDS); + if (!descriptorUUID.equals(confirmed.uuid)) { + this.aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm descriptor write. Got " + confirmed.uuid + ".Expected: " + descriptorUUID + ". Status: " + confirmed.status); + throw new CouldNotConfirmDescriptorWriteException(confirmed.uuid, descriptorUUID); + } + } + + @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + super.onDescriptorWrite(gatt, descriptor, status); + String uuid = null; + if (status == BluetoothGatt.GATT_SUCCESS) { + uuid = descriptor.getUuid().toString(); + } + DescriptorWriteConfirmation confirmation = new DescriptorWriteConfirmation(status, uuid); + try { + if (this.descriptorWriteQueue.size() > 0) { + this.aapsLogger.warn(LTag.PUMPBTCOMM, "Descriptor write queue should be empty, found: "+ this.descriptorWriteQueue.size()); + this.descriptorWriteQueue.clear(); + } + + boolean offered = this.descriptorWriteQueue.offer(confirmation, WRITE_CONFIRM_TIMEOUT_MS, TimeUnit.MILLISECONDS); + if (!offered) { + this.aapsLogger.warn(LTag.PUMPBTCOMM, "Received delayed descriptor write confirmation"); + } + } catch (InterruptedException e) { + this.aapsLogger.warn(LTag.PUMPBTCOMM, "Interrupted while sending descriptor write confirmation"); + } + } +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.java new file mode 100644 index 00000000000..cf2e8bff779 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.java @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks; + +public class CharacteristicWriteConfirmation { + public byte[] payload; + public int status; + + public CharacteristicWriteConfirmation(byte[] payload, int status) { + this.payload = payload; + this.status = status; + } +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.java new file mode 100644 index 00000000000..88ae897b1b3 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.java @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks; + +public class DescriptorWriteConfirmation { + public int status; + public String uuid; + + public DescriptorWriteConfirmation(int status, String uuid) { + this.status = status; + this.uuid = uuid; + } +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.java new file mode 100644 index 00000000000..53f85c5a6f1 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; + +public class BleIOBusyException extends Exception{ +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.java new file mode 100644 index 00000000000..b2034fd087a --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.java @@ -0,0 +1,12 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; + +public class CouldNotConfirmDescriptorWriteException extends Exception{ + private final String received; + private final String expected; + + public CouldNotConfirmDescriptorWriteException(String received, String expected) { + super(); + this.received = received; + this.expected = expected; + } +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.java new file mode 100644 index 00000000000..f422746180e --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.java @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; + +public class CouldNotConfirmWrite extends Exception { + + private final byte[] sent; + private final Object confirmed; + + public CouldNotConfirmWrite(byte[] sent, byte[] confirmed) { + super(); + this.sent = sent; + this.confirmed = confirmed; + } +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.java new file mode 100644 index 00000000000..261490dee50 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.java @@ -0,0 +1,9 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; + +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType; + +public class CouldNotEnableNotifications extends Exception { + public CouldNotEnableNotifications(CharacteristicType cmd) { + super(cmd.getValue()); + } +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.java new file mode 100644 index 00000000000..d7dc3473eb9 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; + +public class DescriptorNotFoundException extends Exception { +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.java new file mode 100644 index 00000000000..75490b33e3d --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.java @@ -0,0 +1,140 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.logging.LTag; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.BleIOBusyException; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotEnableNotifications; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotSendBleException; +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.DescriptorNotFoundException; + + +public class BleIO { + private static final int DEFAULT_IO_TIMEOUT_MS = 1000; + + private final AAPSLogger aapsLogger; + private final Map chars; + private final Map> incomingPackets; + private final BluetoothGatt gatt; + private final BleCommCallbacks bleCommCallbacks; + + private IOState state; + + public BleIO(AAPSLogger aapsLogger, Map chars, Map> incomingPackets, BluetoothGatt gatt, BleCommCallbacks bleCommCallbacks) { + this.aapsLogger = aapsLogger; + this.chars = chars; + this.incomingPackets = incomingPackets; + this.gatt = gatt; + this.bleCommCallbacks = bleCommCallbacks; + this.state = IOState.IDLE; + } + + /*** + * + * @param characteristic where to read from(CMD or DATA) + * @return a byte array with the received data + */ + public byte[] receivePacket(CharacteristicType characteristic) throws + BleIOBusyException, + InterruptedException, + TimeoutException { + synchronized (this.state) { + if (this.state != IOState.IDLE) { + throw new BleIOBusyException(); + } + this.state = IOState.READING; + } + byte[] ret = this.incomingPackets.get(characteristic).poll(DEFAULT_IO_TIMEOUT_MS, TimeUnit.MILLISECONDS); + if (ret == null) { + throw new TimeoutException(); + } + synchronized (this.state) { + this.state = IOState.IDLE; + } + return ret; + } + + /*** + * + * @param characteristic where to write to(CMD or DATA) + * @param payload the data to send + * @throws CouldNotSendBleException + */ + public void sendAndConfirmPacket(CharacteristicType characteristic, byte[] payload) + throws CouldNotSendBleException, + BleIOBusyException, + InterruptedException, + CouldNotConfirmWrite, + TimeoutException { + synchronized (this.state) { + if (this.state != IOState.IDLE) { + throw new BleIOBusyException(); + } + this.state = IOState.WRITING; + } + + aapsLogger.debug(LTag.PUMPBTCOMM, "BleIO: Sending data on" + characteristic.name() + "/" + payload.toString()); + BluetoothGattCharacteristic ch = chars.get(characteristic); + boolean set = ch.setValue(payload); + if (!set) { + throw new CouldNotSendBleException("setValue"); + } + boolean sent = this.gatt.writeCharacteristic(ch); + if (!sent) { + throw new CouldNotSendBleException("writeCharacteristic"); + } + this.bleCommCallbacks.confirmWrite(CharacteristicType.CMD, payload, DEFAULT_IO_TIMEOUT_MS); + synchronized (this.state) { + this.state = IOState.IDLE; + } + } + + /** + * Called before sending a new message. + * The incoming queues should be empty, so we log when they are not. + */ + public void flushIncomingQueues() { + + } + + /** + * Enable intentions on the characteristics. + * This will signal the pod it can start sending back data + * @return + */ + public void readyToRead() + throws CouldNotSendBleException, + CouldNotEnableNotifications, + DescriptorNotFoundException, + InterruptedException, CouldNotConfirmDescriptorWriteException { + + for (CharacteristicType type : CharacteristicType.values()) { + BluetoothGattCharacteristic ch = this.chars.get(type); + boolean notificationSet = this.gatt.setCharacteristicNotification(ch, true); + if (!notificationSet) { + throw new CouldNotEnableNotifications(type); + } + List descriptors = ch.getDescriptors(); + if (descriptors.size() != 1) { + throw new DescriptorNotFoundException(); + } + BluetoothGattDescriptor descriptor = descriptors.get(0); + descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE); + gatt.writeDescriptor(descriptor); + bleCommCallbacks.confirmWriteDescriptor(descriptor.getUuid().toString(), DEFAULT_IO_TIMEOUT_MS); + } + } +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.java new file mode 100644 index 00000000000..cd9ae12297e --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.java @@ -0,0 +1,7 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io; + +public enum IOState { + IDLE, + WRITING, + READING; +} From 647793e0b7ef12ac81f23f7455d64b20e3fcae4a Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Wed, 24 Feb 2021 18:07:19 +0100 Subject: [PATCH 3/6] Switch to Kotlin. and small fixes after conversion --- .../omnipod/dash/driver/comm/BleManager.java | 125 --------------- .../omnipod/dash/driver/comm/BleManager.kt | 99 ++++++++++++ .../dash/driver/comm/CharacteristicType.java | 35 ----- .../dash/driver/comm/CharacteristicType.kt | 26 ++++ ...ava => OmnipodDashCommunicationManager.kt} | 5 +- .../dash/driver/comm/ServiceDiscoverer.java | 75 --------- .../dash/driver/comm/ServiceDiscoverer.kt | 47 ++++++ .../comm/callbacks/BleCommCallbacks.java | 147 ------------------ .../driver/comm/callbacks/BleCommCallbacks.kt | 142 +++++++++++++++++ .../CharacteristicWriteConfirmation.java | 11 -- .../CharacteristicWriteConfirmation.kt | 3 + .../DescriptorWriteConfirmation.java | 11 -- .../callbacks/DescriptorWriteConfirmation.kt | 3 + .../dash/driver/comm/command/BleCommand.java | 22 --- .../dash/driver/comm/command/BleCommand.kt | 21 +++ .../driver/comm/command/BleCommandHello.java | 14 -- .../driver/comm/command/BleCommandHello.kt | 10 ++ .../driver/comm/command/BleCommandType.java | 30 ---- .../driver/comm/command/BleCommandType.kt | 17 ++ .../comm/exceptions/BleIOBusyException.java | 4 - .../comm/exceptions/BleIOBusyException.kt | 3 + .../CharacteristicNotFoundException.java | 7 - .../CharacteristicNotFoundException.kt | 3 + ...uldNotConfirmDescriptorWriteException.java | 12 -- ...CouldNotConfirmDescriptorWriteException.kt | 3 + .../comm/exceptions/CouldNotConfirmWrite.java | 13 -- .../comm/exceptions/CouldNotConfirmWrite.kt | 10 ++ .../CouldNotEnableNotifications.java | 9 -- .../exceptions/CouldNotEnableNotifications.kt | 5 + .../exceptions/CouldNotSendBleException.java | 7 - .../exceptions/CouldNotSendBleException.kt | 3 + .../DescriptorNotFoundException.java | 4 - .../exceptions/DescriptorNotFoundException.kt | 3 + .../DiscoveredInvalidPodException.java | 11 -- .../DiscoveredInvalidPodException.kt | 5 + .../exceptions/FailedToConnectException.java | 11 -- .../exceptions/FailedToConnectException.kt | 6 + .../comm/exceptions/ScanFailException.java | 10 -- .../comm/exceptions/ScanFailException.kt | 6 + .../ScanFailFoundTooManyException.java | 20 --- .../ScanFailFoundTooManyException.kt | 15 ++ .../exceptions/ScanFailNotFoundException.java | 4 - .../exceptions/ScanFailNotFoundException.kt | 3 + .../exceptions/ServiceNotFoundException.java | 7 - .../exceptions/ServiceNotFoundException.kt | 3 + .../omnipod/dash/driver/comm/io/BleIO.java | 140 ----------------- .../pump/omnipod/dash/driver/comm/io/BleIO.kt | 104 +++++++++++++ .../omnipod/dash/driver/comm/io/IOState.java | 7 - .../omnipod/dash/driver/comm/io/IOState.kt | 5 + .../packet/{BlePacket.java => BlePacket.kt} | 5 +- .../driver/comm/scan/BleDiscoveredDevice.java | 94 ----------- .../driver/comm/scan/BleDiscoveredDevice.kt | 78 ++++++++++ .../dash/driver/comm/scan/PodScanner.java | 62 -------- .../dash/driver/comm/scan/PodScanner.kt | 48 ++++++ .../dash/driver/comm/scan/ScanCollector.java | 66 -------- .../dash/driver/comm/scan/ScanCollector.kt | 51 ++++++ 56 files changed, 726 insertions(+), 964 deletions(-) delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt rename omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/{OmnipodDashCommunicationManager.java => OmnipodDashCommunicationManager.kt} (50%) delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandHello.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandHello.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CharacteristicNotFoundException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CharacteristicNotFoundException.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/FailedToConnectException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/FailedToConnectException.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailException.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailFoundTooManyException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailFoundTooManyException.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailNotFoundException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailNotFoundException.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ServiceNotFoundException.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ServiceNotFoundException.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.kt rename omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/packet/{BlePacket.java => BlePacket.kt} (59%) delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/PodScanner.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/PodScanner.kt delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.java create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java deleted file mode 100644 index 35164c4cc17..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.java +++ /dev/null @@ -1,125 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothManager; -import android.bluetooth.BluetoothProfile; -import android.content.Context; - -import java.util.Collections; -import java.util.EnumMap; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.TimeoutException; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.BuildConfig; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.BleCommandHello; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.BleIOBusyException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotEnableNotifications; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.DescriptorNotFoundException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.BleIO; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotSendBleException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.FailedToConnectException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.PodScanner; - -@Singleton -public class BleManager implements OmnipodDashCommunicationManager { - private static final int CONNECT_TIMEOUT_MS = 5000; - private static final int CONTROLLER_ID = 4242; // TODO read from preferences or somewhere else. - - private static BleManager instance = null; - private final Context context; - private final BluetoothAdapter bluetoothAdapter; - private final BluetoothManager bluetoothManager; - @Inject AAPSLogger aapsLogger; - private String podAddress; - private BluetoothGatt gatt; - private BleIO bleio; - - @Inject - public BleManager(Context context) { - this.context = context; - this.bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); - this.bluetoothAdapter = bluetoothManager.getAdapter(); - } - - public static BleManager getInstance(Context context) { - BleManager ret; - synchronized (BleManager.class) { - if (instance == null) { - instance = new BleManager(context); - } - ret = instance; - } - return ret; - } - - public void activateNewPod() - throws InterruptedException, - ScanFailException, - FailedToConnectException, - CouldNotSendBleException, - BleIOBusyException, - TimeoutException, - CouldNotConfirmWrite, CouldNotEnableNotifications, DescriptorNotFoundException, CouldNotConfirmDescriptorWriteException { - this.aapsLogger.info(LTag.PUMPBTCOMM, "starting new pod activation"); - PodScanner podScanner = new PodScanner(this.aapsLogger, this.bluetoothAdapter); - this.podAddress = podScanner.scanForPod(PodScanner.SCAN_FOR_SERVICE_UUID, PodScanner.POD_ID_NOT_ACTIVATED).getScanResult().getDevice().getAddress(); - // For tests: this.podAddress = "B8:27:EB:1D:7E:BB"; - this.connect(); - } - - public void connect() - throws FailedToConnectException, - CouldNotSendBleException, - InterruptedException, - BleIOBusyException, TimeoutException, CouldNotConfirmWrite, CouldNotEnableNotifications, DescriptorNotFoundException, CouldNotConfirmDescriptorWriteException { - // TODO: locking? - - BluetoothDevice podDevice = this.bluetoothAdapter.getRemoteDevice(this.podAddress); - - Map> incomingPackets = new EnumMap>(CharacteristicType.class); - incomingPackets.put(CharacteristicType.CMD, new LinkedBlockingDeque<>()); - incomingPackets.put(CharacteristicType.DATA, new LinkedBlockingDeque<>()); - incomingPackets = Collections.unmodifiableMap(incomingPackets); - - BleCommCallbacks bleCommCallbacks = new BleCommCallbacks(aapsLogger, incomingPackets); - - aapsLogger.debug(LTag.PUMPBTCOMM, "Connecting to " + this.podAddress); - boolean autoConnect = true; - if (BuildConfig.DEBUG) { - autoConnect = false; - // TODO: remove this in the future - // it's easier to start testing from scratch on each run. - } - gatt = podDevice.connectGatt(this.context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE); - - bleCommCallbacks.waitForConnection(CONNECT_TIMEOUT_MS); - - int connectionState = this.bluetoothManager.getConnectionState(podDevice, BluetoothProfile.GATT); - aapsLogger.debug(LTag.PUMPBTCOMM, "GATT connection state: " + connectionState); - if (connectionState != BluetoothProfile.STATE_CONNECTED) { - throw new FailedToConnectException(this.podAddress); - } - - ServiceDiscoverer discoverer = new ServiceDiscoverer(this.aapsLogger, gatt, bleCommCallbacks); - Map chars = discoverer.discoverServices(); - - this.bleio = new BleIO(aapsLogger, chars, incomingPackets, gatt, bleCommCallbacks); - this.aapsLogger.debug(LTag.PUMPBTCOMM, "Saying hello to the pod"); - this.bleio.sendAndConfirmPacket(CharacteristicType.CMD, new BleCommandHello(CONTROLLER_ID).asByteArray()); - this.bleio.readyToRead(); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt new file mode 100644 index 00000000000..630d57c1b9a --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt @@ -0,0 +1,99 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm + + +import javax.inject.Singleton +import javax.inject.Inject +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashCommunicationManager +import android.bluetooth.BluetoothAdapter +import android.bluetooth.BluetoothManager +import info.nightscout.androidaps.logging.AAPSLogger +import android.bluetooth.BluetoothGatt +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.BleIO +import kotlin.Throws +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailException +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.FailedToConnectException +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotSendBleException +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.BleIOBusyException +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotEnableNotifications +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.DescriptorNotFoundException +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.PodScanner +import android.bluetooth.BluetoothDevice +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.BleManager +import android.bluetooth.BluetoothProfile +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.ServiceDiscoverer +import android.bluetooth.BluetoothGattCharacteristic +import android.content.Context +import info.nightscout.androidaps.plugins.pump.omnipod.dash.BuildConfig +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.BleCommandHello +import java.util.* +import java.util.concurrent.BlockingQueue +import java.util.concurrent.LinkedBlockingDeque +import java.util.concurrent.TimeoutException + +@Singleton +class BleManager @Inject constructor(private val context: Context) : OmnipodDashCommunicationManager { + + private val bluetoothAdapter: BluetoothAdapter + private val bluetoothManager: BluetoothManager + + @Inject lateinit var aapsLogger: AAPSLogger + private var podAddress: String? = null + private var gatt: BluetoothGatt? = null + private var bleio: BleIO? = null + @Throws(InterruptedException::class, ScanFailException::class, FailedToConnectException::class, CouldNotSendBleException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWrite::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class) + fun activateNewPod() { + aapsLogger.info(LTag.PUMPBTCOMM, "starting new pod activation") + val podScanner = PodScanner(aapsLogger, bluetoothAdapter) + podAddress = podScanner.scanForPod(PodScanner.SCAN_FOR_SERVICE_UUID, PodScanner.POD_ID_NOT_ACTIVATED).scanResult.device.address + // For tests: this.podAddress = "B8:27:EB:1D:7E:BB"; + connect() + } + + @Throws(FailedToConnectException::class, CouldNotSendBleException::class, InterruptedException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWrite::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class) + fun connect() { + // TODO: locking? + val podDevice = bluetoothAdapter.getRemoteDevice(podAddress) + var incomingPackets: Map> = + mapOf(CharacteristicType.CMD to LinkedBlockingDeque(), + CharacteristicType.DATA to LinkedBlockingDeque()); + val bleCommCallbacks = BleCommCallbacks(aapsLogger, incomingPackets) + aapsLogger.debug(LTag.PUMPBTCOMM, "Connecting to " + podAddress) + var autoConnect = true + if (BuildConfig.DEBUG) { + autoConnect = false + // TODO: remove this in the future + // it's easier to start testing from scratch on each run. + } + val gatt = podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE) + this.gatt = gatt + + bleCommCallbacks.waitForConnection(CONNECT_TIMEOUT_MS) + val connectionState = bluetoothManager.getConnectionState(podDevice, BluetoothProfile.GATT) + aapsLogger.debug(LTag.PUMPBTCOMM, "GATT connection state: $connectionState") + if (connectionState != BluetoothProfile.STATE_CONNECTED) { + throw FailedToConnectException(podAddress) + } + val discoverer = ServiceDiscoverer(aapsLogger, gatt, bleCommCallbacks) + val chars = discoverer.discoverServices() + bleio = BleIO(aapsLogger, chars, incomingPackets, gatt, bleCommCallbacks) + aapsLogger.debug(LTag.PUMPBTCOMM, "Saying hello to the pod") + bleio!!.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandHello(CONTROLLER_ID).asByteArray()) + bleio!!.readyToRead() + } + + companion object { + + private const val CONNECT_TIMEOUT_MS = 5000 + private const val CONTROLLER_ID = 4242 // TODO read from preferences or somewhere else. + } + + init { + bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager + bluetoothAdapter = bluetoothManager.adapter + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java deleted file mode 100644 index 73bcc9de61d..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.java +++ /dev/null @@ -1,35 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm; - -import java.math.BigInteger; -import java.util.UUID; - -public enum CharacteristicType { - CMD("1a7e2441-e3ed-4464-8b7e-751e03d0dc5f"), - DATA("1a7e2442-e3ed-4464-8b7e-751e03d0dc5f"); - - public final String value; - - CharacteristicType(String value) { - this.value = value; - } - - public static CharacteristicType byValue(String value) { - for (CharacteristicType type : values()) { - if (type.value.equals(value)) { - return type; - } - } - throw new IllegalArgumentException("Unknown Characteristic Type: " + value); - } - - public String getValue() { - return this.value; - } - - public UUID getUUID() { - return new UUID( - new BigInteger(this.value.replace("-", "").substring(0, 16), 16).longValue(), - new BigInteger(this.value.replace("-", "").substring(16), 16).longValue() - ); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt new file mode 100644 index 00000000000..600e4ba769b --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm + +import java.math.BigInteger +import java.util.* + +enum class CharacteristicType(val value: String) { + CMD("1a7e2441-e3ed-4464-8b7e-751e03d0dc5f"), DATA("1a7e2442-e3ed-4464-8b7e-751e03d0dc5f"); + + val uUID: UUID + get() = UUID( + BigInteger(value.replace("-", "").substring(0, 16), 16).toLong(), + BigInteger(value.replace("-", "").substring(16), 16).toLong() + ) + + companion object { + + @JvmStatic fun byValue(value: String): CharacteristicType { + for (type in values()) { + if (type.value == value) { + return type + } + } + throw IllegalArgumentException("Unknown Characteristic Type: $value") + } + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashCommunicationManager.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashCommunicationManager.kt similarity index 50% rename from omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashCommunicationManager.java rename to omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashCommunicationManager.kt index a53f3e2b344..db95a2046be 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashCommunicationManager.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/OmnipodDashCommunicationManager.kt @@ -1,4 +1,3 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm; +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm -public interface OmnipodDashCommunicationManager { -} +interface OmnipodDashCommunicationManager \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java deleted file mode 100644 index 13828db4d0a..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.java +++ /dev/null @@ -1,75 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattService; - -import java.math.BigInteger; -import java.util.Collections; -import java.util.EnumMap; -import java.util.Map; -import java.util.UUID; - -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CharacteristicNotFoundException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ServiceNotFoundException; - -public class ServiceDiscoverer { - private static final String SERVICE_UUID = "1a7e-4024-e3ed-4464-8b7e-751e03d0dc5f"; - private static final int DISCOVER_SERVICES_TIMEOUT_MS = 5000; - - private final BluetoothGatt gatt; - private final BleCommCallbacks bleCallbacks; - private final AAPSLogger logger; - private Map chars; - - public ServiceDiscoverer(AAPSLogger logger, BluetoothGatt gatt, BleCommCallbacks bleCallbacks) { - this.gatt = gatt; - this.bleCallbacks = bleCallbacks; - this.logger = logger; - } - - private static UUID uuidFromString(String s) { - return new UUID( - new BigInteger(s.replace("-", "").substring(0, 16), 16).longValue(), - new BigInteger(s.replace("-", "").substring(16), 16).longValue() - ); - } - - /*** - * This is first step after connection establishment - */ - public Map discoverServices() - throws InterruptedException, - ServiceNotFoundException, - CharacteristicNotFoundException { - - logger.debug(LTag.PUMPBTCOMM, "Discovering services"); - gatt.discoverServices(); - this.bleCallbacks.waitForServiceDiscovery(DISCOVER_SERVICES_TIMEOUT_MS); - logger.debug(LTag.PUMPBTCOMM, "Services discovered"); - - BluetoothGattService service = gatt.getService( - uuidFromString(SERVICE_UUID)); - if (service == null) { - throw new ServiceNotFoundException(SERVICE_UUID); - } - BluetoothGattCharacteristic cmdChar = service.getCharacteristic(CharacteristicType.CMD.getUUID()); - if (cmdChar == null) { - throw new CharacteristicNotFoundException(CharacteristicType.CMD.getValue()); - } - BluetoothGattCharacteristic dataChar = service.getCharacteristic(CharacteristicType.DATA.getUUID()); - if (dataChar == null) { - throw new CharacteristicNotFoundException(CharacteristicType.DATA.getValue()); - } - Map chars = new EnumMap(CharacteristicType.class); - chars.put(CharacteristicType.CMD, cmdChar); - chars.put(CharacteristicType.DATA, dataChar); - this.chars = Collections.unmodifiableMap(chars); - return this.chars; - } - -} - diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt new file mode 100644 index 00000000000..85694a213a0 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt @@ -0,0 +1,47 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm + +import android.bluetooth.BluetoothGatt +import android.bluetooth.BluetoothGattCharacteristic +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CharacteristicNotFoundException +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ServiceNotFoundException +import java.math.BigInteger +import java.util.* + +class ServiceDiscoverer(private val logger: AAPSLogger, private val gatt: BluetoothGatt, private val bleCallbacks: BleCommCallbacks) { + + /*** + * This is first step after connection establishment + */ + @Throws(InterruptedException::class, ServiceNotFoundException::class, CharacteristicNotFoundException::class) + fun discoverServices(): Map { + logger.debug(LTag.PUMPBTCOMM, "Discovering services") + gatt.discoverServices() + bleCallbacks.waitForServiceDiscovery(DISCOVER_SERVICES_TIMEOUT_MS) + logger.debug(LTag.PUMPBTCOMM, "Services discovered") + val service = gatt.getService( + uuidFromString(SERVICE_UUID)) + ?: throw ServiceNotFoundException(SERVICE_UUID) + val cmdChar = service.getCharacteristic(CharacteristicType.CMD.uUID) + ?: throw CharacteristicNotFoundException(CharacteristicType.CMD.value) + val dataChar = service.getCharacteristic(CharacteristicType.DATA.uUID) + ?: throw CharacteristicNotFoundException(CharacteristicType.DATA.value) + var chars = mapOf(CharacteristicType.CMD to cmdChar, + CharacteristicType.DATA to dataChar) + return chars + } + + companion object { + private const val SERVICE_UUID = "1a7e-4024-e3ed-4464-8b7e-751e03d0dc5f" + private const val DISCOVER_SERVICES_TIMEOUT_MS = 5000 + private fun uuidFromString(s: String): UUID { + return UUID( + BigInteger(s.replace("-", "").substring(0, 16), 16).toLong(), + BigInteger(s.replace("-", "").substring(16), 16).toLong() + ) + } + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.java deleted file mode 100644 index 28a202606e7..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.java +++ /dev/null @@ -1,147 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCallback; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattDescriptor; -import android.bluetooth.BluetoothProfile; - -import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite; - -public class BleCommCallbacks extends BluetoothGattCallback { - private final static int WRITE_CONFIRM_TIMEOUT_MS = 10; // the other thread should be waiting for the exchange - - private final CountDownLatch serviceDiscoveryComplete; - private final CountDownLatch connected; - private final AAPSLogger aapsLogger; - private final Map> incomingPackets; - private final BlockingQueue writeQueue; - private final BlockingQueue descriptorWriteQueue; - - public BleCommCallbacks(AAPSLogger aapsLogger, Map> incomingPackets) { - this.serviceDiscoveryComplete = new CountDownLatch(1); - this.connected = new CountDownLatch(1); - this.aapsLogger = aapsLogger; - this.incomingPackets = incomingPackets; - this.writeQueue = new LinkedBlockingQueue<>(1); - this.descriptorWriteQueue = new LinkedBlockingQueue<>(1); - } - - @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - super.onConnectionStateChange(gatt, status, newState); - this.aapsLogger.debug(LTag.PUMPBTCOMM, "OnConnectionStateChange discovered with status/state" + status + "/" + newState); - if (newState == BluetoothProfile.STATE_CONNECTED && status == BluetoothGatt.GATT_SUCCESS) { - this.connected.countDown(); - } - } - - @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { - super.onServicesDiscovered(gatt, status); - this.aapsLogger.debug(LTag.PUMPBTCOMM, "OnServicesDiscovered with status" + status); - if (status == BluetoothGatt.GATT_SUCCESS) { - this.serviceDiscoveryComplete.countDown(); - } - } - - public void waitForConnection(int timeout_ms) - throws InterruptedException { - this.connected.await(timeout_ms, TimeUnit.MILLISECONDS); - } - - public void waitForServiceDiscovery(int timeout_ms) - throws InterruptedException { - this.serviceDiscoveryComplete.await(timeout_ms, TimeUnit.MILLISECONDS); - } - - public void confirmWrite(CharacteristicType characteristicType, byte[] expectedPayload, int timeout_ms) throws InterruptedException, TimeoutException, CouldNotConfirmWrite { - CharacteristicWriteConfirmation received = this.writeQueue.poll(timeout_ms, TimeUnit.MILLISECONDS); - if (received == null ) { - throw new TimeoutException(); - } - if (!Arrays.equals(expectedPayload, received.payload)) { - this.aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm write. Got " + received.payload + ".Excepted: " + expectedPayload + ". Status: "+received.status); - throw new CouldNotConfirmWrite(expectedPayload, received.payload); - } - this.aapsLogger.debug(LTag.PUMPBTCOMM, "Confirmed write with value: " + received.payload); - } - - @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { - super.onCharacteristicWrite(gatt, characteristic, status); - byte[] received = null; - - if (status == BluetoothGatt.GATT_SUCCESS) { - received = characteristic.getValue(); - this.aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicWrite value " + characteristic.getStringValue(0)); - } - - this.aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicWrite with status/char/value " + - status + "/" + - CharacteristicType.byValue(characteristic.getUuid().toString()) + "/" + - received); - try { - if (this.writeQueue.size() > 0) { - this.aapsLogger.warn(LTag.PUMPBTCOMM, "Write confirm queue should be empty. found: "+ this.writeQueue.size()); - this.writeQueue.clear(); - } - boolean offered = this.writeQueue.offer(new CharacteristicWriteConfirmation(received, status), WRITE_CONFIRM_TIMEOUT_MS, TimeUnit.MILLISECONDS); - if (!offered) { - this.aapsLogger.warn(LTag.PUMPBTCOMM, "Received delayed write confirmation"); - } - } catch (InterruptedException e) { - this.aapsLogger.warn(LTag.PUMPBTCOMM, "Interrupted while sending write confirmation"); - } - } - - @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - super.onCharacteristicChanged(gatt, characteristic); - - byte[] payload = characteristic.getValue(); - CharacteristicType characteristicType = CharacteristicType.byValue(characteristic.getUuid().toString()); - this.aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicChanged with char/value " + - characteristicType + "/" + - payload); - this.incomingPackets.get(characteristicType).add(payload); - } - - public void confirmWriteDescriptor(String descriptorUUID, int timeout_ms) throws InterruptedException, CouldNotConfirmDescriptorWriteException { - DescriptorWriteConfirmation confirmed = this.descriptorWriteQueue.poll(timeout_ms, TimeUnit.MILLISECONDS); - if (!descriptorUUID.equals(confirmed.uuid)) { - this.aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm descriptor write. Got " + confirmed.uuid + ".Expected: " + descriptorUUID + ". Status: " + confirmed.status); - throw new CouldNotConfirmDescriptorWriteException(confirmed.uuid, descriptorUUID); - } - } - - @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { - super.onDescriptorWrite(gatt, descriptor, status); - String uuid = null; - if (status == BluetoothGatt.GATT_SUCCESS) { - uuid = descriptor.getUuid().toString(); - } - DescriptorWriteConfirmation confirmation = new DescriptorWriteConfirmation(status, uuid); - try { - if (this.descriptorWriteQueue.size() > 0) { - this.aapsLogger.warn(LTag.PUMPBTCOMM, "Descriptor write queue should be empty, found: "+ this.descriptorWriteQueue.size()); - this.descriptorWriteQueue.clear(); - } - - boolean offered = this.descriptorWriteQueue.offer(confirmation, WRITE_CONFIRM_TIMEOUT_MS, TimeUnit.MILLISECONDS); - if (!offered) { - this.aapsLogger.warn(LTag.PUMPBTCOMM, "Received delayed descriptor write confirmation"); - } - } catch (InterruptedException e) { - this.aapsLogger.warn(LTag.PUMPBTCOMM, "Interrupted while sending descriptor write confirmation"); - } - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt new file mode 100644 index 00000000000..1998d9b3075 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt @@ -0,0 +1,142 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks + +import android.bluetooth.BluetoothGatt +import android.bluetooth.BluetoothGattCallback +import android.bluetooth.BluetoothGattCharacteristic +import android.bluetooth.BluetoothGattDescriptor +import android.bluetooth.BluetoothProfile +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType.Companion.byValue +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite +import java.util.* +import java.util.concurrent.BlockingQueue +import java.util.concurrent.CountDownLatch +import java.util.concurrent.LinkedBlockingQueue +import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeoutException + +class BleCommCallbacks(aapsLogger: AAPSLogger, incomingPackets: Map>) : BluetoothGattCallback() { + + private val serviceDiscoveryComplete: CountDownLatch + private val connected: CountDownLatch + private val aapsLogger: AAPSLogger + private val incomingPackets: Map> + private val writeQueue: BlockingQueue + private val descriptorWriteQueue: BlockingQueue + override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) { + super.onConnectionStateChange(gatt, status, newState) + aapsLogger.debug(LTag.PUMPBTCOMM, "OnConnectionStateChange discovered with status/state$status/$newState") + if (newState == BluetoothProfile.STATE_CONNECTED && status == BluetoothGatt.GATT_SUCCESS) { + connected.countDown() + } + } + + override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) { + super.onServicesDiscovered(gatt, status) + aapsLogger.debug(LTag.PUMPBTCOMM, "OnServicesDiscovered with status$status") + if (status == BluetoothGatt.GATT_SUCCESS) { + serviceDiscoveryComplete.countDown() + } + } + + @Throws(InterruptedException::class) fun waitForConnection(timeout_ms: Int) { + connected.await(timeout_ms.toLong(), TimeUnit.MILLISECONDS) + } + + @Throws(InterruptedException::class) fun waitForServiceDiscovery(timeout_ms: Int) { + serviceDiscoveryComplete.await(timeout_ms.toLong(), TimeUnit.MILLISECONDS) + } + + @Throws(InterruptedException::class, TimeoutException::class, CouldNotConfirmWrite::class) + fun confirmWrite(expectedPayload: ByteArray, timeout_ms: Int) { + val received = writeQueue.poll(timeout_ms.toLong(), TimeUnit.MILLISECONDS) + ?: throw TimeoutException() + if (!Arrays.equals(expectedPayload, received.payload)) { + aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm write. Got " + received.payload + ".Excepted: " + expectedPayload + ". Status: " + received.status) + throw CouldNotConfirmWrite(expectedPayload, received.payload!!) + } + aapsLogger.debug(LTag.PUMPBTCOMM, "Confirmed write with value: " + received.payload) + } + + override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) { + super.onCharacteristicWrite(gatt, characteristic, status) + var received: ByteArray? = null + if (status == BluetoothGatt.GATT_SUCCESS) { + received = characteristic.value + aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicWrite value " + characteristic.getStringValue(0)) + } + aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicWrite with status/char/value " + + status + "/" + + byValue(characteristic.uuid.toString()) + "/" + + received) + try { + if (writeQueue.size > 0) { + aapsLogger.warn(LTag.PUMPBTCOMM, "Write confirm queue should be empty. found: " + writeQueue.size) + writeQueue.clear() + } + val offered = writeQueue.offer(CharacteristicWriteConfirmation(received, status), WRITE_CONFIRM_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS) + if (!offered) { + aapsLogger.warn(LTag.PUMPBTCOMM, "Received delayed write confirmation") + } + } catch (e: InterruptedException) { + aapsLogger.warn(LTag.PUMPBTCOMM, "Interrupted while sending write confirmation") + } + } + + override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { + super.onCharacteristicChanged(gatt, characteristic) + val payload = characteristic.value + val characteristicType = byValue(characteristic.uuid.toString()) + aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicChanged with char/value " + + characteristicType + "/" + + payload) + incomingPackets[characteristicType]!!.add(payload) + } + + @Throws(InterruptedException::class, CouldNotConfirmDescriptorWriteException::class) + fun confirmWriteDescriptor(descriptorUUID: String, timeout_ms: Int) { + val confirmed = descriptorWriteQueue.poll(timeout_ms.toLong(), TimeUnit.MILLISECONDS) + if (descriptorUUID != confirmed.uuid) { + aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm descriptor write. Got " + confirmed.uuid + ".Expected: " + descriptorUUID + ". Status: " + confirmed.status) + throw CouldNotConfirmDescriptorWriteException(confirmed.uuid!!, descriptorUUID) + } + } + + override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) { + super.onDescriptorWrite(gatt, descriptor, status) + var uuid: String? = null + if (status == BluetoothGatt.GATT_SUCCESS) { + uuid = descriptor.uuid.toString() + } + val confirmation = DescriptorWriteConfirmation(status, uuid) + try { + if (descriptorWriteQueue.size > 0) { + aapsLogger.warn(LTag.PUMPBTCOMM, "Descriptor write queue should be empty, found: " + descriptorWriteQueue.size) + descriptorWriteQueue.clear() + } + val offered = descriptorWriteQueue.offer(confirmation, WRITE_CONFIRM_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS) + if (!offered) { + aapsLogger.warn(LTag.PUMPBTCOMM, "Received delayed descriptor write confirmation") + } + } catch (e: InterruptedException) { + aapsLogger.warn(LTag.PUMPBTCOMM, "Interrupted while sending descriptor write confirmation") + } + } + + companion object { + + private const val WRITE_CONFIRM_TIMEOUT_MS = 10 // the other thread should be waiting for the exchange + } + + init { + serviceDiscoveryComplete = CountDownLatch(1) + connected = CountDownLatch(1) + this.aapsLogger = aapsLogger + this.incomingPackets = incomingPackets + writeQueue = LinkedBlockingQueue(1) + descriptorWriteQueue = LinkedBlockingQueue(1) + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.java deleted file mode 100644 index cf2e8bff779..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.java +++ /dev/null @@ -1,11 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks; - -public class CharacteristicWriteConfirmation { - public byte[] payload; - public int status; - - public CharacteristicWriteConfirmation(byte[] payload, int status) { - this.payload = payload; - this.status = status; - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.kt new file mode 100644 index 00000000000..76a5db2f632 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks + +class CharacteristicWriteConfirmation(var payload: ByteArray?, var status: Int) \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.java deleted file mode 100644 index 88ae897b1b3..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.java +++ /dev/null @@ -1,11 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks; - -public class DescriptorWriteConfirmation { - public int status; - public String uuid; - - public DescriptorWriteConfirmation(int status, String uuid) { - this.status = status; - this.uuid = uuid; - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.kt new file mode 100644 index 00000000000..c975393d7cb --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks + +class DescriptorWriteConfirmation(var status: Int, var uuid: String?) \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.java deleted file mode 100644 index 4af111d6337..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.java +++ /dev/null @@ -1,22 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command; - -import org.jetbrains.annotations.NotNull; - -public abstract class BleCommand { - private final byte[] data; - - public BleCommand(@NotNull BleCommandType type) { - this.data = new byte[]{type.getValue()}; - } - - public BleCommand(@NotNull BleCommandType type, @NotNull byte[] payload) { - int n = payload.length + 1; - this.data = new byte[n]; - this.data[0] = type.getValue(); - System.arraycopy(payload, 0, data, 1, payload.length); - } - - public byte[] asByteArray() { - return this.data; - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.kt new file mode 100644 index 00000000000..d5483f3d37c --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.kt @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command + +abstract class BleCommand { + + private val data: ByteArray + + constructor(type: BleCommandType) { + data = byteArrayOf(type.value) + } + + constructor(type: BleCommandType, payload: ByteArray) { + val n = payload.size + 1 + data = ByteArray(n) + data[0] = type.value + System.arraycopy(payload, 0, data, 1, payload.size) + } + + fun asByteArray(): ByteArray { + return data + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandHello.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandHello.java deleted file mode 100644 index 56659f45e5c..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandHello.java +++ /dev/null @@ -1,14 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command; - -import java.nio.ByteBuffer; - -public class BleCommandHello extends BleCommand { - public BleCommandHello(int controllerId) { - super(BleCommandType.HELLO, - ByteBuffer.allocate(6) - .put((byte) 1) // TODO find the meaning of this constant - .put((byte) 4) // TODO find the meaning of this constant - .putInt(controllerId).array() - ); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandHello.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandHello.kt new file mode 100644 index 00000000000..03414989b25 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandHello.kt @@ -0,0 +1,10 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command + +import java.nio.ByteBuffer + +class BleCommandHello(controllerId: Int) : BleCommand(BleCommandType.HELLO, + ByteBuffer.allocate(6) + .put(1.toByte()) // TODO find the meaning of this constant + .put(4.toByte()) // TODO find the meaning of this constant + .putInt(controllerId).array() +) \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.java deleted file mode 100644 index 38225bf799c..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.java +++ /dev/null @@ -1,30 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command; - -public enum BleCommandType { - RTS((byte) 0x00), - CTS((byte) 0x01), - NACK((byte) 0x02), - ABORT((byte) 0x03), - SUCCESS((byte) 0x04), - FAIL((byte) 0x05), - HELLO((byte) 0x06); - - public final byte value; - - BleCommandType(byte value) { - this.value = value; - } - - public static BleCommandType byValue(byte value) { - for (BleCommandType type : values()) { - if (type.value == value) { - return type; - } - } - throw new IllegalArgumentException("Unknown BleCommandType: " + value); - } - - public byte getValue() { - return this.value; - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.kt new file mode 100644 index 00000000000..7dd91d00e1f --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.kt @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command + +enum class BleCommandType(val value: Byte) { + RTS(0x00.toByte()), CTS(0x01.toByte()), NACK(0x02.toByte()), ABORT(0x03.toByte()), SUCCESS(0x04.toByte()), FAIL(0x05.toByte()), HELLO(0x06.toByte()); + + companion object { + + fun byValue(value: Byte): BleCommandType { + for (type in values()) { + if (type.value == value) { + return type + } + } + throw IllegalArgumentException("Unknown BleCommandType: $value") + } + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.java deleted file mode 100644 index 53f85c5a6f1..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.java +++ /dev/null @@ -1,4 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -public class BleIOBusyException extends Exception{ -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.kt new file mode 100644 index 00000000000..6029d669983 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/BleIOBusyException.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +class BleIOBusyException : Exception() \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CharacteristicNotFoundException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CharacteristicNotFoundException.java deleted file mode 100644 index 1405d93f32d..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CharacteristicNotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -public class CharacteristicNotFoundException extends FailedToConnectException { - public CharacteristicNotFoundException(String cmdCharacteristicUuid) { - super("characteristic not found: " + cmdCharacteristicUuid); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CharacteristicNotFoundException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CharacteristicNotFoundException.kt new file mode 100644 index 00000000000..730b6eeda02 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CharacteristicNotFoundException.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +class CharacteristicNotFoundException(cmdCharacteristicUuid: String) : FailedToConnectException("characteristic not found: $cmdCharacteristicUuid") \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.java deleted file mode 100644 index b2034fd087a..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.java +++ /dev/null @@ -1,12 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -public class CouldNotConfirmDescriptorWriteException extends Exception{ - private final String received; - private final String expected; - - public CouldNotConfirmDescriptorWriteException(String received, String expected) { - super(); - this.received = received; - this.expected = expected; - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.kt new file mode 100644 index 00000000000..0b49f749705 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +class CouldNotConfirmDescriptorWriteException(private val received: String, private val expected: String) : Exception() \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.java deleted file mode 100644 index f422746180e..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.java +++ /dev/null @@ -1,13 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -public class CouldNotConfirmWrite extends Exception { - - private final byte[] sent; - private final Object confirmed; - - public CouldNotConfirmWrite(byte[] sent, byte[] confirmed) { - super(); - this.sent = sent; - this.confirmed = confirmed; - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.kt new file mode 100644 index 00000000000..cb815ce34cb --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.kt @@ -0,0 +1,10 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +class CouldNotConfirmWrite(private val sent: ByteArray, confirmed: ByteArray) : Exception() { + + private val confirmed: Any + + init { + this.confirmed = confirmed + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.java deleted file mode 100644 index 261490dee50..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.java +++ /dev/null @@ -1,9 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType; - -public class CouldNotEnableNotifications extends Exception { - public CouldNotEnableNotifications(CharacteristicType cmd) { - super(cmd.getValue()); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.kt new file mode 100644 index 00000000000..7564ab32e16 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotEnableNotifications.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType + +class CouldNotEnableNotifications(cmd: CharacteristicType) : Exception(cmd.value) \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.java deleted file mode 100644 index 6bd30f5ff82..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.java +++ /dev/null @@ -1,7 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -public class CouldNotSendBleException extends Exception { - public CouldNotSendBleException(String msg) { - super(msg); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.kt new file mode 100644 index 00000000000..63abcb9a680 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotSendBleException.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +class CouldNotSendBleException(msg: String?) : Exception(msg) \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.java deleted file mode 100644 index d7dc3473eb9..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.java +++ /dev/null @@ -1,4 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -public class DescriptorNotFoundException extends Exception { -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.kt new file mode 100644 index 00000000000..202fcaf3b1d --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DescriptorNotFoundException.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +class DescriptorNotFoundException : Exception() \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.java deleted file mode 100644 index 9de20faf07c..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.java +++ /dev/null @@ -1,11 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -import android.os.ParcelUuid; - -import java.util.List; - -public class DiscoveredInvalidPodException extends Exception { - public DiscoveredInvalidPodException(String message, List serviceUUIds) { - super(message + " service UUIDs: " + serviceUUIds); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.kt new file mode 100644 index 00000000000..9b8ff7488d1 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +import android.os.ParcelUuid + +class DiscoveredInvalidPodException(message: String, serviceUUIds: List) : Exception("$message service UUIDs: $serviceUUIds") \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/FailedToConnectException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/FailedToConnectException.java deleted file mode 100644 index dd4cf724edf..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/FailedToConnectException.java +++ /dev/null @@ -1,11 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -public class FailedToConnectException extends Exception { - public FailedToConnectException() { - super(); - } - - public FailedToConnectException(String message) { - super(message); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/FailedToConnectException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/FailedToConnectException.kt new file mode 100644 index 00000000000..c720724ceb0 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/FailedToConnectException.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +open class FailedToConnectException : Exception { + constructor() : super() {} + constructor(message: String?) : super(message) {} +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailException.java deleted file mode 100644 index f99fbe32d43..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailException.java +++ /dev/null @@ -1,10 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -public class ScanFailException extends Exception { - public ScanFailException() { - } - - public ScanFailException(int errorCode) { - super("errorCode" + errorCode); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailException.kt new file mode 100644 index 00000000000..6c6dcc2f49c --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailException.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +open class ScanFailException : Exception { + constructor() {} + constructor(errorCode: Int) : super("errorCode$errorCode") {} +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailFoundTooManyException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailFoundTooManyException.java deleted file mode 100644 index 7fc00ae2df6..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailFoundTooManyException.java +++ /dev/null @@ -1,20 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.BleDiscoveredDevice; - -public class ScanFailFoundTooManyException extends ScanFailException { - private final List devices; - - public ScanFailFoundTooManyException(List devices) { - super(); - this.devices = new ArrayList<>(devices); - } - - public List getDiscoveredDevices() { - return Collections.unmodifiableList(this.devices); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailFoundTooManyException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailFoundTooManyException.kt new file mode 100644 index 00000000000..d83b6643e80 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailFoundTooManyException.kt @@ -0,0 +1,15 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.BleDiscoveredDevice +import java.util.* + +class ScanFailFoundTooManyException(devices: List?) : ScanFailException() { + + private val devices: List + val discoveredDevices: List + get() = Collections.unmodifiableList(devices) + + init { + this.devices = ArrayList(devices) + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailNotFoundException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailNotFoundException.java deleted file mode 100644 index 9bf2284db32..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailNotFoundException.java +++ /dev/null @@ -1,4 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -public class ScanFailNotFoundException extends ScanFailException { -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailNotFoundException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailNotFoundException.kt new file mode 100644 index 00000000000..9466ea9b52b --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ScanFailNotFoundException.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +class ScanFailNotFoundException : ScanFailException() \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ServiceNotFoundException.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ServiceNotFoundException.java deleted file mode 100644 index 51bfa5b8ef6..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ServiceNotFoundException.java +++ /dev/null @@ -1,7 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions; - -public class ServiceNotFoundException extends FailedToConnectException { - public ServiceNotFoundException(String serviceUuid) { - super("service not found: " + serviceUuid); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ServiceNotFoundException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ServiceNotFoundException.kt new file mode 100644 index 00000000000..dc792f5825d --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/ServiceNotFoundException.kt @@ -0,0 +1,3 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +class ServiceNotFoundException(serviceUuid: String) : FailedToConnectException("service not found: $serviceUuid") \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.java deleted file mode 100644 index 75490b33e3d..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.java +++ /dev/null @@ -1,140 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattDescriptor; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.BleIOBusyException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotEnableNotifications; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotSendBleException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.DescriptorNotFoundException; - - -public class BleIO { - private static final int DEFAULT_IO_TIMEOUT_MS = 1000; - - private final AAPSLogger aapsLogger; - private final Map chars; - private final Map> incomingPackets; - private final BluetoothGatt gatt; - private final BleCommCallbacks bleCommCallbacks; - - private IOState state; - - public BleIO(AAPSLogger aapsLogger, Map chars, Map> incomingPackets, BluetoothGatt gatt, BleCommCallbacks bleCommCallbacks) { - this.aapsLogger = aapsLogger; - this.chars = chars; - this.incomingPackets = incomingPackets; - this.gatt = gatt; - this.bleCommCallbacks = bleCommCallbacks; - this.state = IOState.IDLE; - } - - /*** - * - * @param characteristic where to read from(CMD or DATA) - * @return a byte array with the received data - */ - public byte[] receivePacket(CharacteristicType characteristic) throws - BleIOBusyException, - InterruptedException, - TimeoutException { - synchronized (this.state) { - if (this.state != IOState.IDLE) { - throw new BleIOBusyException(); - } - this.state = IOState.READING; - } - byte[] ret = this.incomingPackets.get(characteristic).poll(DEFAULT_IO_TIMEOUT_MS, TimeUnit.MILLISECONDS); - if (ret == null) { - throw new TimeoutException(); - } - synchronized (this.state) { - this.state = IOState.IDLE; - } - return ret; - } - - /*** - * - * @param characteristic where to write to(CMD or DATA) - * @param payload the data to send - * @throws CouldNotSendBleException - */ - public void sendAndConfirmPacket(CharacteristicType characteristic, byte[] payload) - throws CouldNotSendBleException, - BleIOBusyException, - InterruptedException, - CouldNotConfirmWrite, - TimeoutException { - synchronized (this.state) { - if (this.state != IOState.IDLE) { - throw new BleIOBusyException(); - } - this.state = IOState.WRITING; - } - - aapsLogger.debug(LTag.PUMPBTCOMM, "BleIO: Sending data on" + characteristic.name() + "/" + payload.toString()); - BluetoothGattCharacteristic ch = chars.get(characteristic); - boolean set = ch.setValue(payload); - if (!set) { - throw new CouldNotSendBleException("setValue"); - } - boolean sent = this.gatt.writeCharacteristic(ch); - if (!sent) { - throw new CouldNotSendBleException("writeCharacteristic"); - } - this.bleCommCallbacks.confirmWrite(CharacteristicType.CMD, payload, DEFAULT_IO_TIMEOUT_MS); - synchronized (this.state) { - this.state = IOState.IDLE; - } - } - - /** - * Called before sending a new message. - * The incoming queues should be empty, so we log when they are not. - */ - public void flushIncomingQueues() { - - } - - /** - * Enable intentions on the characteristics. - * This will signal the pod it can start sending back data - * @return - */ - public void readyToRead() - throws CouldNotSendBleException, - CouldNotEnableNotifications, - DescriptorNotFoundException, - InterruptedException, CouldNotConfirmDescriptorWriteException { - - for (CharacteristicType type : CharacteristicType.values()) { - BluetoothGattCharacteristic ch = this.chars.get(type); - boolean notificationSet = this.gatt.setCharacteristicNotification(ch, true); - if (!notificationSet) { - throw new CouldNotEnableNotifications(type); - } - List descriptors = ch.getDescriptors(); - if (descriptors.size() != 1) { - throw new DescriptorNotFoundException(); - } - BluetoothGattDescriptor descriptor = descriptors.get(0); - descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE); - gatt.writeDescriptor(descriptor); - bleCommCallbacks.confirmWriteDescriptor(descriptor.getUuid().toString(), DEFAULT_IO_TIMEOUT_MS); - } - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt new file mode 100644 index 00000000000..7dfe2a44b4a --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt @@ -0,0 +1,104 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io + +import android.bluetooth.BluetoothGatt +import android.bluetooth.BluetoothGattCharacteristic +import android.bluetooth.BluetoothGattDescriptor +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.* +import java.util.concurrent.BlockingQueue +import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeoutException + +class BleIO(private val aapsLogger: AAPSLogger, private val chars: Map, private val incomingPackets: Map>, private val gatt: BluetoothGatt, private val bleCommCallbacks: BleCommCallbacks) { + + private var state: IOState + + /*** + * + * @param characteristic where to read from(CMD or DATA) + * @return a byte array with the received data + */ + @Throws(BleIOBusyException::class, InterruptedException::class, TimeoutException::class) + fun receivePacket(characteristic: CharacteristicType): ByteArray { + synchronized(state) { + if (state != IOState.IDLE) { + throw BleIOBusyException() + } + state = IOState.READING + } + val ret = incomingPackets[characteristic]!!.poll(DEFAULT_IO_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS) + ?: throw TimeoutException() + synchronized(state) { state = IOState.IDLE } + return ret + } + + /*** + * + * @param characteristic where to write to(CMD or DATA) + * @param payload the data to send + * @throws CouldNotSendBleException + */ + @Throws(CouldNotSendBleException::class, BleIOBusyException::class, InterruptedException::class, CouldNotConfirmWrite::class, TimeoutException::class) + fun sendAndConfirmPacket(characteristic: CharacteristicType, payload: ByteArray) { + synchronized(state) { + if (state != IOState.IDLE) { + throw BleIOBusyException() + } + state = IOState.WRITING + } + aapsLogger.debug(LTag.PUMPBTCOMM, "BleIO: Sending data on" + characteristic.name + "/" + payload.toString()) + val ch = chars[characteristic] + val set = ch!!.setValue(payload) + if (!set) { + throw CouldNotSendBleException("setValue") + } + val sent = gatt.writeCharacteristic(ch) + if (!sent) { + throw CouldNotSendBleException("writeCharacteristic") + } + bleCommCallbacks.confirmWrite(payload, DEFAULT_IO_TIMEOUT_MS) + synchronized(state) { state = IOState.IDLE } + } + + /** + * Called before sending a new message. + * The incoming queues should be empty, so we log when they are not. + */ + fun flushIncomingQueues() {} + + /** + * Enable intentions on the characteristics. + * This will signal the pod it can start sending back data + * @return + */ + @Throws(CouldNotSendBleException::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, InterruptedException::class, CouldNotConfirmDescriptorWriteException::class) + fun readyToRead() { + for (type in CharacteristicType.values()) { + val ch = chars[type] + val notificationSet = gatt.setCharacteristicNotification(ch, true) + if (!notificationSet) { + throw CouldNotEnableNotifications(type) + } + val descriptors = ch!!.descriptors + if (descriptors.size != 1) { + throw DescriptorNotFoundException() + } + val descriptor = descriptors[0] + descriptor.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE + gatt.writeDescriptor(descriptor) + bleCommCallbacks.confirmWriteDescriptor(descriptor.uuid.toString(), DEFAULT_IO_TIMEOUT_MS) + } + } + + companion object { + + private const val DEFAULT_IO_TIMEOUT_MS = 1000 + } + + init { + state = IOState.IDLE + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.java deleted file mode 100644 index cd9ae12297e..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.java +++ /dev/null @@ -1,7 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io; - -public enum IOState { - IDLE, - WRITING, - READING; -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.kt new file mode 100644 index 00000000000..4ef49f65867 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/IOState.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io + +enum class IOState { + IDLE, WRITING, READING +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/packet/BlePacket.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/packet/BlePacket.kt similarity index 59% rename from omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/packet/BlePacket.java rename to omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/packet/BlePacket.kt index 54babad0499..6e8e7de891b 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/packet/BlePacket.java +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/packet/BlePacket.kt @@ -1,4 +1,3 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet; +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet -public class BlePacket { -} +class BlePacket \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.java deleted file mode 100644 index d4c0a19ef81..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.java +++ /dev/null @@ -1,94 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan; - -import android.bluetooth.le.ScanRecord; -import android.bluetooth.le.ScanResult; -import android.os.ParcelUuid; - -import java.util.List; - -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.DiscoveredInvalidPodException; - -public class BleDiscoveredDevice { - private final ScanResult scanResult; - private final long podID; - private final int sequenceNo; - private final long lotNo; - - public BleDiscoveredDevice(ScanResult scanResult, long searchPodID) - throws DiscoveredInvalidPodException { - - this.scanResult = scanResult; - this.podID = searchPodID; - - this.validateServiceUUIDs(); - this.validatePodID(); - this.lotNo = this.parseLotNo(); - this.sequenceNo = this.parseSeqNo(); - } - - private static String extractUUID16(ParcelUuid uuid) { - return uuid.toString().substring(4, 8); - } - - private void validateServiceUUIDs() - throws DiscoveredInvalidPodException { - ScanRecord scanRecord = scanResult.getScanRecord(); - List serviceUUIDs = scanRecord.getServiceUuids(); - - if (serviceUUIDs.size() != 9) { - throw new DiscoveredInvalidPodException("Expected 9 service UUIDs, got" + serviceUUIDs.size(), serviceUUIDs); - } - if (!extractUUID16(serviceUUIDs.get(0)).equals("4024")) { - // this is the service that we filtered for - throw new DiscoveredInvalidPodException("The first exposed service UUID should be 4024, got " + extractUUID16(serviceUUIDs.get(0)), serviceUUIDs); - } - // TODO understand what is serviceUUIDs[1]. 0x2470. Alarms? - if (!extractUUID16(serviceUUIDs.get(2)).equals("000a")) { - // constant? - throw new DiscoveredInvalidPodException("The third exposed service UUID should be 000a, got " + serviceUUIDs.get(2), serviceUUIDs); - } - } - - private void validatePodID() - throws DiscoveredInvalidPodException { - ScanRecord scanRecord = scanResult.getScanRecord(); - List serviceUUIDs = scanRecord.getServiceUuids(); - String hexPodID = extractUUID16(serviceUUIDs.get(3)) + extractUUID16(serviceUUIDs.get(4)); - Long podID = Long.parseLong(hexPodID, 16); - if (this.podID != podID) { - throw new DiscoveredInvalidPodException("This is not the POD we are looking for. " + this.podID + " found: " + podID, serviceUUIDs); - } - } - - private long parseLotNo() { - ScanRecord scanRecord = scanResult.getScanRecord(); - List serviceUUIDs = scanRecord.getServiceUuids(); - String lotSeq = extractUUID16(serviceUUIDs.get(5)) + - extractUUID16(serviceUUIDs.get(6)) + - extractUUID16(serviceUUIDs.get(7)); - - return Long.parseLong(lotSeq.substring(0, 10), 16); - } - - private int parseSeqNo() { - ScanRecord scanRecord = scanResult.getScanRecord(); - List serviceUUIDs = scanRecord.getServiceUuids(); - String lotSeq = extractUUID16(serviceUUIDs.get(7)) + - extractUUID16(serviceUUIDs.get(8)); - - return Integer.parseInt(lotSeq.substring(2), 16); - } - - public ScanResult getScanResult() { - return this.scanResult; - } - - @Override public String toString() { - return "BleDiscoveredDevice{" + - "scanResult=" + scanResult + - ", podID=" + podID + - ", sequenceNo=" + sequenceNo + - ", lotNo=" + lotNo + - '}'; - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.kt new file mode 100644 index 00000000000..dba4b8d8b55 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.kt @@ -0,0 +1,78 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan + +import android.bluetooth.le.ScanResult +import android.os.ParcelUuid +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.DiscoveredInvalidPodException + +class BleDiscoveredDevice(val scanResult: ScanResult, private val podID: Long) { + + private val sequenceNo: Int + private val lotNo: Long + @Throws(DiscoveredInvalidPodException::class) private fun validateServiceUUIDs() { + val scanRecord = scanResult.scanRecord + ?: throw DiscoveredInvalidPodException("Scan record is null") + val serviceUUIDs = scanRecord.serviceUuids + if (serviceUUIDs.size != 9) { + throw DiscoveredInvalidPodException("Expected 9 service UUIDs, got" + serviceUUIDs.size, serviceUUIDs) + } + if (extractUUID16(serviceUUIDs[0]) != "4024") { + // this is the service that we filtered for + throw DiscoveredInvalidPodException("The first exposed service UUID should be 4024, got " + extractUUID16(serviceUUIDs[0]), serviceUUIDs) + } + // TODO understand what is serviceUUIDs[1]. 0x2470. Alarms? + if (extractUUID16(serviceUUIDs[2]) != "000a") { + // constant? + throw DiscoveredInvalidPodException("The third exposed service UUID should be 000a, got " + serviceUUIDs[2], serviceUUIDs) + } + } + + @Throws(DiscoveredInvalidPodException::class) private fun validatePodID() { + val scanRecord = scanResult.scanRecord + val serviceUUIDs = scanRecord.serviceUuids + val hexPodID = extractUUID16(serviceUUIDs[3]) + extractUUID16(serviceUUIDs[4]) + val podID = hexPodID.toLong(16) + if (this.podID != podID) { + throw DiscoveredInvalidPodException("This is not the POD we are looking for. " + this.podID + " found: " + podID, serviceUUIDs) + } + } + + private fun parseLotNo(): Long { + val scanRecord = scanResult.scanRecord + val serviceUUIDs = scanRecord.serviceUuids + val lotSeq = extractUUID16(serviceUUIDs[5]) + + extractUUID16(serviceUUIDs[6]) + + extractUUID16(serviceUUIDs[7]) + return lotSeq.substring(0, 10).toLong(16) + } + + private fun parseSeqNo(): Int { + val scanRecord = scanResult.scanRecord + val serviceUUIDs = scanRecord.serviceUuids + val lotSeq = extractUUID16(serviceUUIDs[7]) + + extractUUID16(serviceUUIDs[8]) + return lotSeq.substring(2).toInt(16) + } + + override fun toString(): String { + return "BleDiscoveredDevice{" + + "scanResult=" + scanResult + + ", podID=" + podID + + ", sequenceNo=" + sequenceNo + + ", lotNo=" + lotNo + + '}' + } + + companion object { + + private fun extractUUID16(uuid: ParcelUuid): String { + return uuid.toString().substring(4, 8) + } + } + + init { + validateServiceUUIDs() + validatePodID() + lotNo = parseLotNo() + sequenceNo = parseSeqNo() + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/PodScanner.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/PodScanner.java deleted file mode 100644 index c3953f75d19..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/PodScanner.java +++ /dev/null @@ -1,62 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.le.BluetoothLeScanner; -import android.bluetooth.le.ScanFilter; -import android.bluetooth.le.ScanSettings; -import android.os.ParcelUuid; - -import java.util.Arrays; -import java.util.List; - -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailFoundTooManyException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailNotFoundException; - -public class PodScanner { - public static final String SCAN_FOR_SERVICE_UUID = "00004024-0000-1000-8000-00805F9B34FB"; - public static final long POD_ID_NOT_ACTIVATED = 4294967294L; - private static final int SCAN_DURATION_MS = 5000; - - private final BluetoothAdapter bluetoothAdapter; - private final AAPSLogger logger; - - public PodScanner(AAPSLogger logger, BluetoothAdapter bluetoothAdapter) { - this.bluetoothAdapter = bluetoothAdapter; - this.logger = logger; - } - - public BleDiscoveredDevice scanForPod(String serviceUUID, long podID) - throws InterruptedException, ScanFailException { - BluetoothLeScanner scanner = this.bluetoothAdapter.getBluetoothLeScanner(); - - ScanFilter filter = new ScanFilter.Builder() - .setServiceUuid(ParcelUuid.fromString(serviceUUID)) - .build(); - - ScanSettings scanSettings = new ScanSettings.Builder() - .setLegacy(false) - .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) - .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) - .build(); - - ScanCollector scanCollector = new ScanCollector(this.logger, podID); - this.logger.debug(LTag.PUMPBTCOMM, "Scanning with filters: "+ filter.toString() + " settings" + scanSettings.toString()); - scanner.startScan(Arrays.asList(filter), scanSettings, scanCollector); - - Thread.sleep(SCAN_DURATION_MS); - - scanner.flushPendingScanResults(scanCollector); - scanner.stopScan(scanCollector); - - List collected = scanCollector.collect(); - if (collected.size() == 0) { - throw new ScanFailNotFoundException(); - } else if (collected.size() > 1) { - throw new ScanFailFoundTooManyException(collected); - } - return collected.get(0); - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/PodScanner.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/PodScanner.kt new file mode 100644 index 00000000000..829faaa4056 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/PodScanner.kt @@ -0,0 +1,48 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan + +import android.bluetooth.BluetoothAdapter +import android.bluetooth.le.ScanFilter +import android.bluetooth.le.ScanSettings +import android.os.ParcelUuid +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailException +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailFoundTooManyException +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailNotFoundException +import java.util.* + +class PodScanner(private val logger: AAPSLogger, private val bluetoothAdapter: BluetoothAdapter) { + + @Throws(InterruptedException::class, ScanFailException::class) + fun scanForPod(serviceUUID: String?, podID: Long): BleDiscoveredDevice { + val scanner = bluetoothAdapter.bluetoothLeScanner + val filter = ScanFilter.Builder() + .setServiceUuid(ParcelUuid.fromString(serviceUUID)) + .build() + val scanSettings = ScanSettings.Builder() + .setLegacy(false) + .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) + .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) + .build() + val scanCollector = ScanCollector(logger, podID) + logger.debug(LTag.PUMPBTCOMM, "Scanning with filters: $filter settings$scanSettings") + scanner.startScan(Arrays.asList(filter), scanSettings, scanCollector) + Thread.sleep(SCAN_DURATION_MS.toLong()) + scanner.flushPendingScanResults(scanCollector) + scanner.stopScan(scanCollector) + val collected = scanCollector.collect() + if (collected.size == 0) { + throw ScanFailNotFoundException() + } else if (collected.size > 1) { + throw ScanFailFoundTooManyException(collected) + } + return collected[0] + } + + companion object { + + const val SCAN_FOR_SERVICE_UUID = "00004024-0000-1000-8000-00805F9B34FB" + const val POD_ID_NOT_ACTIVATED = 4294967294L + private const val SCAN_DURATION_MS = 5000 + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.java b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.java deleted file mode 100644 index 9121b0f5a42..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.java +++ /dev/null @@ -1,66 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan; - -import android.bluetooth.le.ScanCallback; -import android.bluetooth.le.ScanResult; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; - -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.DiscoveredInvalidPodException; -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailException; - -public class ScanCollector extends ScanCallback { - private final AAPSLogger logger; - private final long podID; - // there could be different threads calling the onScanResult callback - private final ConcurrentHashMap found; - private int scanFailed; - - public ScanCollector(AAPSLogger logger, long podID) { - this.podID = podID; - this.logger = logger; - this.found = new ConcurrentHashMap(); - } - - @Override - public void onScanResult(int callbackType, ScanResult result) { - // callbackType will be ALL - this.logger.debug(LTag.PUMPBTCOMM, "Scan found: "+result.toString()); - this.found.put(result.getDevice().getAddress(), result); - } - - @Override - public void onScanFailed(int errorCode) { - this.scanFailed = errorCode; - this.logger.warn(LTag.PUMPBTCOMM, "Scan failed with errorCode: "+errorCode); - super.onScanFailed(errorCode); - } - - public List collect() - throws ScanFailException { - List ret = new ArrayList<>(); - - if (this.scanFailed != 0) { - throw new ScanFailException(this.scanFailed); - } - - logger.debug(LTag.PUMPBTCOMM, "ScanCollector looking for podID: " + this.podID); - - for (ScanResult result : this.found.values()) { - try { - BleDiscoveredDevice device = new BleDiscoveredDevice(result, this.podID); - ret.add(device); - logger.debug(LTag.PUMPBTCOMM, "ScanCollector found: " + result.toString() + "Pod ID: " + this.podID); - } catch (DiscoveredInvalidPodException e) { - logger.debug(LTag.PUMPBTCOMM, "ScanCollector: pod not matching" + e.toString()); - // this is not the POD we are looking for - } - } - return Collections.unmodifiableList(ret); - } -} - diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt new file mode 100644 index 00000000000..d37f7148548 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt @@ -0,0 +1,51 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan + +import android.bluetooth.le.ScanCallback +import android.bluetooth.le.ScanResult +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.DiscoveredInvalidPodException +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailException +import java.util.* +import java.util.concurrent.ConcurrentHashMap + +class ScanCollector(private val logger: AAPSLogger, private val podID: Long) : ScanCallback() { + + // there could be different threads calling the onScanResult callback + private val found: ConcurrentHashMap + private var scanFailed = 0 + override fun onScanResult(callbackType: Int, result: ScanResult) { + // callbackType will be ALL + logger.debug(LTag.PUMPBTCOMM, "Scan found: $result") + found[result.device.address] = result + } + + override fun onScanFailed(errorCode: Int) { + scanFailed = errorCode + logger.warn(LTag.PUMPBTCOMM, "Scan failed with errorCode: $errorCode") + super.onScanFailed(errorCode) + } + + @Throws(ScanFailException::class) fun collect(): List { + val ret: MutableList = ArrayList() + if (scanFailed != 0) { + throw ScanFailException(scanFailed) + } + logger.debug(LTag.PUMPBTCOMM, "ScanCollector looking for podID: " + podID) + for (result in found.values) { + try { + val device = BleDiscoveredDevice(result, podID) + ret.add(device) + logger.debug(LTag.PUMPBTCOMM, "ScanCollector found: " + result.toString() + "Pod ID: " + podID) + } catch (e: DiscoveredInvalidPodException) { + logger.debug(LTag.PUMPBTCOMM, "ScanCollector: pod not matching$e") + // this is not the POD we are looking for + } + } + return Collections.unmodifiableList(ret) + } + + init { + found = ConcurrentHashMap() + } +} \ No newline at end of file From 2a14d60beed923a71f435efea9624a7f2f867232 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Wed, 24 Feb 2021 20:12:29 +0100 Subject: [PATCH 4/6] kotlin a bit more idiomatic after conversion from Java --- .../omnipod/dash/driver/comm/BleManager.kt | 65 ++++++------------- .../dash/driver/comm/CharacteristicType.kt | 12 ++-- .../dash/driver/comm/ServiceDiscoverer.kt | 19 +++--- .../driver/comm/callbacks/BleCommCallbacks.kt | 58 ++++++++--------- .../CharacteristicWriteConfirmation.kt | 6 +- .../driver/comm/command/BleCommandType.kt | 11 +--- .../comm/exceptions/CouldNotConfirmWrite.kt | 9 +-- .../ScanFailFoundTooManyException.kt | 8 +-- .../pump/omnipod/dash/driver/comm/io/BleIO.kt | 8 +-- .../dash/driver/comm/scan/PodScanner.kt | 2 +- .../dash/driver/comm/scan/ScanCollector.kt | 7 +- 11 files changed, 78 insertions(+), 127 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt index 630d57c1b9a..a227adab186 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt @@ -1,68 +1,49 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm - -import javax.inject.Singleton -import javax.inject.Inject -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashCommunicationManager import android.bluetooth.BluetoothAdapter -import android.bluetooth.BluetoothManager -import info.nightscout.androidaps.logging.AAPSLogger -import android.bluetooth.BluetoothGatt -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.BleIO -import kotlin.Throws -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ScanFailException -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.FailedToConnectException -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotSendBleException -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.BleIOBusyException -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotEnableNotifications -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.DescriptorNotFoundException -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException -import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.PodScanner import android.bluetooth.BluetoothDevice -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.BleManager +import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothProfile -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.ServiceDiscoverer -import android.bluetooth.BluetoothGattCharacteristic import android.content.Context +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.omnipod.dash.BuildConfig +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.BleCommandHello +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.* +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.BleIO +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.PodScanner import java.util.* import java.util.concurrent.BlockingQueue import java.util.concurrent.LinkedBlockingDeque import java.util.concurrent.TimeoutException +import javax.inject.Inject +import javax.inject.Singleton @Singleton -class BleManager @Inject constructor(private val context: Context) : OmnipodDashCommunicationManager { +class BleManager @Inject constructor(private val context: Context, private val aapsLogger: AAPSLogger) : OmnipodDashCommunicationManager { - private val bluetoothAdapter: BluetoothAdapter - private val bluetoothManager: BluetoothManager + private val bluetoothManager: BluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager + private val bluetoothAdapter: BluetoothAdapter = bluetoothManager.adapter - @Inject lateinit var aapsLogger: AAPSLogger - private var podAddress: String? = null - private var gatt: BluetoothGatt? = null - private var bleio: BleIO? = null @Throws(InterruptedException::class, ScanFailException::class, FailedToConnectException::class, CouldNotSendBleException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWrite::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class) fun activateNewPod() { aapsLogger.info(LTag.PUMPBTCOMM, "starting new pod activation") val podScanner = PodScanner(aapsLogger, bluetoothAdapter) - podAddress = podScanner.scanForPod(PodScanner.SCAN_FOR_SERVICE_UUID, PodScanner.POD_ID_NOT_ACTIVATED).scanResult.device.address + val podAddress = podScanner.scanForPod(PodScanner.SCAN_FOR_SERVICE_UUID, PodScanner.POD_ID_NOT_ACTIVATED).scanResult.device.address // For tests: this.podAddress = "B8:27:EB:1D:7E:BB"; - connect() + connect(podAddress) } @Throws(FailedToConnectException::class, CouldNotSendBleException::class, InterruptedException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWrite::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class) - fun connect() { + private fun connect(podAddress: String) { // TODO: locking? val podDevice = bluetoothAdapter.getRemoteDevice(podAddress) - var incomingPackets: Map> = + val incomingPackets: Map> = mapOf(CharacteristicType.CMD to LinkedBlockingDeque(), CharacteristicType.DATA to LinkedBlockingDeque()); val bleCommCallbacks = BleCommCallbacks(aapsLogger, incomingPackets) - aapsLogger.debug(LTag.PUMPBTCOMM, "Connecting to " + podAddress) + aapsLogger.debug(LTag.PUMPBTCOMM, "Connecting to $podAddress") var autoConnect = true if (BuildConfig.DEBUG) { autoConnect = false @@ -70,8 +51,6 @@ class BleManager @Inject constructor(private val context: Context) : OmnipodDash // it's easier to start testing from scratch on each run. } val gatt = podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE) - this.gatt = gatt - bleCommCallbacks.waitForConnection(CONNECT_TIMEOUT_MS) val connectionState = bluetoothManager.getConnectionState(podDevice, BluetoothProfile.GATT) aapsLogger.debug(LTag.PUMPBTCOMM, "GATT connection state: $connectionState") @@ -80,10 +59,10 @@ class BleManager @Inject constructor(private val context: Context) : OmnipodDash } val discoverer = ServiceDiscoverer(aapsLogger, gatt, bleCommCallbacks) val chars = discoverer.discoverServices() - bleio = BleIO(aapsLogger, chars, incomingPackets, gatt, bleCommCallbacks) + val bleIO = BleIO(aapsLogger, chars, incomingPackets, gatt, bleCommCallbacks) aapsLogger.debug(LTag.PUMPBTCOMM, "Saying hello to the pod") - bleio!!.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandHello(CONTROLLER_ID).asByteArray()) - bleio!!.readyToRead() + bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandHello(CONTROLLER_ID).asByteArray()) + bleIO.readyToRead() } companion object { @@ -92,8 +71,4 @@ class BleManager @Inject constructor(private val context: Context) : OmnipodDash private const val CONTROLLER_ID = 4242 // TODO read from preferences or somewhere else. } - init { - bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager - bluetoothAdapter = bluetoothManager.adapter - } } \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt index 600e4ba769b..a68ccba4483 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt @@ -14,13 +14,9 @@ enum class CharacteristicType(val value: String) { companion object { - @JvmStatic fun byValue(value: String): CharacteristicType { - for (type in values()) { - if (type.value == value) { - return type - } - } - throw IllegalArgumentException("Unknown Characteristic Type: $value") - } + @JvmStatic + fun byValue(value: String): CharacteristicType = + values().firstOrNull { it.value == value } + ?: throw IllegalArgumentException("Unknown Characteristic Type: $value") } } \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt index 85694a213a0..ccf7298a6e1 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt @@ -22,26 +22,25 @@ class ServiceDiscoverer(private val logger: AAPSLogger, private val gatt: Blueto gatt.discoverServices() bleCallbacks.waitForServiceDiscovery(DISCOVER_SERVICES_TIMEOUT_MS) logger.debug(LTag.PUMPBTCOMM, "Services discovered") - val service = gatt.getService( - uuidFromString(SERVICE_UUID)) + val service = gatt.getService(SERVICE_UUID.toUuid()) ?: throw ServiceNotFoundException(SERVICE_UUID) val cmdChar = service.getCharacteristic(CharacteristicType.CMD.uUID) ?: throw CharacteristicNotFoundException(CharacteristicType.CMD.value) - val dataChar = service.getCharacteristic(CharacteristicType.DATA.uUID) + val dataChar = service.getCharacteristic(CharacteristicType.DATA.uUID) // TODO: this is never used ?: throw CharacteristicNotFoundException(CharacteristicType.DATA.value) var chars = mapOf(CharacteristicType.CMD to cmdChar, CharacteristicType.DATA to dataChar) return chars } + + private fun String.toUuid(): UUID = UUID( + BigInteger(replace("-", "").substring(0, 16), 16).toLong(), + BigInteger(replace("-", "").substring(16), 16).toLong() + ) + companion object { private const val SERVICE_UUID = "1a7e-4024-e3ed-4464-8b7e-751e03d0dc5f" private const val DISCOVER_SERVICES_TIMEOUT_MS = 5000 - private fun uuidFromString(s: String): UUID { - return UUID( - BigInteger(s.replace("-", "").substring(0, 16), 16).toLong(), - BigInteger(s.replace("-", "").substring(16), 16).toLong() - ) - } } -} \ No newline at end of file +} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt index 1998d9b3075..e6d9dd545e5 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt @@ -11,21 +11,19 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Characte import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType.Companion.byValue import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite -import java.util.* import java.util.concurrent.BlockingQueue import java.util.concurrent.CountDownLatch import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.TimeUnit import java.util.concurrent.TimeoutException -class BleCommCallbacks(aapsLogger: AAPSLogger, incomingPackets: Map>) : BluetoothGattCallback() { +class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingPackets: Map>) : BluetoothGattCallback() { + + private val serviceDiscoveryComplete: CountDownLatch = CountDownLatch(1) + private val connected: CountDownLatch = CountDownLatch(1) + private val writeQueue: BlockingQueue = LinkedBlockingQueue(1) + private val descriptorWriteQueue: BlockingQueue = LinkedBlockingQueue(1) - private val serviceDiscoveryComplete: CountDownLatch - private val connected: CountDownLatch - private val aapsLogger: AAPSLogger - private val incomingPackets: Map> - private val writeQueue: BlockingQueue - private val descriptorWriteQueue: BlockingQueue override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) { super.onConnectionStateChange(gatt, status, newState) aapsLogger.debug(LTag.PUMPBTCOMM, "OnConnectionStateChange discovered with status/state$status/$newState") @@ -42,42 +40,53 @@ class BleCommCallbacks(aapsLogger: AAPSLogger, incomingPackets: Map confirmWritePayload(expectedPayload, received) + is CharacteristicWriteConfirmationError -> + aapsLogger.debug(LTag.PUMPBTCOMM, "Could not confirm write: status was ${received.status}") + } + + } + + private fun confirmWritePayload(expectedPayload: ByteArray, received: CharacteristicWriteConfirmationPayload) { + if (!expectedPayload.contentEquals(received.payload)) { aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm write. Got " + received.payload + ".Excepted: " + expectedPayload + ". Status: " + received.status) - throw CouldNotConfirmWrite(expectedPayload, received.payload!!) + throw CouldNotConfirmWrite(expectedPayload, received.payload) } aapsLogger.debug(LTag.PUMPBTCOMM, "Confirmed write with value: " + received.payload) } override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) { super.onCharacteristicWrite(gatt, characteristic, status) - var received: ByteArray? = null - if (status == BluetoothGatt.GATT_SUCCESS) { - received = characteristic.value + val writeConfirmation = if (status == BluetoothGatt.GATT_SUCCESS) { aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicWrite value " + characteristic.getStringValue(0)) + CharacteristicWriteConfirmationPayload(characteristic.value, status) + } else { + CharacteristicWriteConfirmationError(status) } aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicWrite with status/char/value " + - status + "/" + - byValue(characteristic.uuid.toString()) + "/" + - received) + status + "/" + byValue(characteristic.uuid.toString()) + "/" + characteristic.value) try { if (writeQueue.size > 0) { aapsLogger.warn(LTag.PUMPBTCOMM, "Write confirm queue should be empty. found: " + writeQueue.size) writeQueue.clear() } - val offered = writeQueue.offer(CharacteristicWriteConfirmation(received, status), WRITE_CONFIRM_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS) + val offered = writeQueue.offer(writeConfirmation, WRITE_CONFIRM_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS) if (!offered) { aapsLogger.warn(LTag.PUMPBTCOMM, "Received delayed write confirmation") } @@ -130,13 +139,4 @@ class BleCommCallbacks(aapsLogger: AAPSLogger, incomingPackets: Map?) : ScanFailException() { +class ScanFailFoundTooManyException(devices: List) : ScanFailException() { - private val devices: List + private val devices: List = ArrayList(devices) val discoveredDevices: List get() = Collections.unmodifiableList(devices) - - init { - this.devices = ArrayList(devices) - } } \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt index 7dfe2a44b4a..397520820ca 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt @@ -14,7 +14,7 @@ import java.util.concurrent.TimeoutException class BleIO(private val aapsLogger: AAPSLogger, private val chars: Map, private val incomingPackets: Map>, private val gatt: BluetoothGatt, private val bleCommCallbacks: BleCommCallbacks) { - private var state: IOState + private var state: IOState = IOState.IDLE /*** * @@ -29,7 +29,7 @@ class BleIO(private val aapsLogger: AAPSLogger, private val chars: Map 1) { throw ScanFailFoundTooManyException(collected) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt index d37f7148548..11648159707 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt @@ -12,7 +12,7 @@ import java.util.concurrent.ConcurrentHashMap class ScanCollector(private val logger: AAPSLogger, private val podID: Long) : ScanCallback() { // there could be different threads calling the onScanResult callback - private val found: ConcurrentHashMap + private val found: ConcurrentHashMap = ConcurrentHashMap() private var scanFailed = 0 override fun onScanResult(callbackType: Int, result: ScanResult) { // callbackType will be ALL @@ -31,7 +31,7 @@ class ScanCollector(private val logger: AAPSLogger, private val podID: Long) : S if (scanFailed != 0) { throw ScanFailException(scanFailed) } - logger.debug(LTag.PUMPBTCOMM, "ScanCollector looking for podID: " + podID) + logger.debug(LTag.PUMPBTCOMM, "ScanCollector looking for podID: $podID") for (result in found.values) { try { val device = BleDiscoveredDevice(result, podID) @@ -45,7 +45,4 @@ class ScanCollector(private val logger: AAPSLogger, private val podID: Long) : S return Collections.unmodifiableList(ret) } - init { - found = ConcurrentHashMap() - } } \ No newline at end of file From f2fed8adc4c3c77fda7ab450373864df1a67bb9d Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Thu, 25 Feb 2021 09:31:50 +0100 Subject: [PATCH 5/6] Implement more suggestions after the switch to Kotlin --- .../omnipod/dash/driver/comm/BleManager.kt | 7 ++- .../driver/comm/callbacks/BleCommCallbacks.kt | 43 ++++++++++--------- .../CharacteristicWriteConfirmation.kt | 4 +- .../callbacks/DescriptorWriteConfirmation.kt | 6 ++- .../dash/driver/comm/command/BleCommand.kt | 6 +-- ...CouldNotConfirmDescriptorWriteException.kt | 5 ++- .../comm/exceptions/CouldNotConfirmWrite.kt | 3 -- .../CouldNotConfirmWriteException.kt | 6 +++ .../DiscoveredInvalidPodException.kt | 5 ++- .../pump/omnipod/dash/driver/comm/io/BleIO.kt | 2 +- .../driver/comm/scan/BleDiscoveredDevice.kt | 8 ++-- 11 files changed, 54 insertions(+), 41 deletions(-) delete mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.kt create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWriteException.kt diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt index a227adab186..16d6153b581 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/BleManager.kt @@ -13,7 +13,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command. import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.* import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.BleIO import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.PodScanner -import java.util.* import java.util.concurrent.BlockingQueue import java.util.concurrent.LinkedBlockingDeque import java.util.concurrent.TimeoutException @@ -26,7 +25,7 @@ class BleManager @Inject constructor(private val context: Context, private val a private val bluetoothManager: BluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager private val bluetoothAdapter: BluetoothAdapter = bluetoothManager.adapter - @Throws(InterruptedException::class, ScanFailException::class, FailedToConnectException::class, CouldNotSendBleException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWrite::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class) + @Throws(InterruptedException::class, ScanFailException::class, FailedToConnectException::class, CouldNotSendBleException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWriteException::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class) fun activateNewPod() { aapsLogger.info(LTag.PUMPBTCOMM, "starting new pod activation") val podScanner = PodScanner(aapsLogger, bluetoothAdapter) @@ -35,7 +34,7 @@ class BleManager @Inject constructor(private val context: Context, private val a connect(podAddress) } - @Throws(FailedToConnectException::class, CouldNotSendBleException::class, InterruptedException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWrite::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class) + @Throws(FailedToConnectException::class, CouldNotSendBleException::class, InterruptedException::class, BleIOBusyException::class, TimeoutException::class, CouldNotConfirmWriteException::class, CouldNotEnableNotifications::class, DescriptorNotFoundException::class, CouldNotConfirmDescriptorWriteException::class) private fun connect(podAddress: String) { // TODO: locking? val podDevice = bluetoothAdapter.getRemoteDevice(podAddress) @@ -61,7 +60,7 @@ class BleManager @Inject constructor(private val context: Context, private val a val chars = discoverer.discoverServices() val bleIO = BleIO(aapsLogger, chars, incomingPackets, gatt, bleCommCallbacks) aapsLogger.debug(LTag.PUMPBTCOMM, "Saying hello to the pod") - bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandHello(CONTROLLER_ID).asByteArray()) + bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandHello(CONTROLLER_ID).data) bleIO.readyToRead() } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt index e6d9dd545e5..daf3db26a4f 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt @@ -10,7 +10,7 @@ import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType.Companion.byValue import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmDescriptorWriteException -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWrite +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotConfirmWriteException import java.util.concurrent.BlockingQueue import java.util.concurrent.CountDownLatch import java.util.concurrent.LinkedBlockingQueue @@ -50,23 +50,21 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP serviceDiscoveryComplete.await(timeout_ms.toLong(), TimeUnit.MILLISECONDS) } - @Throws(InterruptedException::class, TimeoutException::class, CouldNotConfirmWrite::class) + @Throws(InterruptedException::class, TimeoutException::class, CouldNotConfirmWriteException::class) fun confirmWrite(expectedPayload: ByteArray, timeout_ms: Int) { val received: CharacteristicWriteConfirmation = writeQueue.poll(timeout_ms.toLong(), TimeUnit.MILLISECONDS) ?: throw TimeoutException() when (received) { is CharacteristicWriteConfirmationPayload -> confirmWritePayload(expectedPayload, received) - is CharacteristicWriteConfirmationError -> - aapsLogger.debug(LTag.PUMPBTCOMM, "Could not confirm write: status was ${received.status}") + is CharacteristicWriteConfirmationError -> throw CouldNotConfirmWriteException(received.status) } - } private fun confirmWritePayload(expectedPayload: ByteArray, received: CharacteristicWriteConfirmationPayload) { if (!expectedPayload.contentEquals(received.payload)) { - aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm write. Got " + received.payload + ".Excepted: " + expectedPayload + ". Status: " + received.status) - throw CouldNotConfirmWrite(expectedPayload, received.payload) + aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm write. Got " + received.payload + ".Excepted: " + expectedPayload) + throw CouldNotConfirmWriteException(expectedPayload, received.payload) } aapsLogger.debug(LTag.PUMPBTCOMM, "Confirmed write with value: " + received.payload) } @@ -74,8 +72,7 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) { super.onCharacteristicWrite(gatt, characteristic, status) val writeConfirmation = if (status == BluetoothGatt.GATT_SUCCESS) { - aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicWrite value " + characteristic.getStringValue(0)) - CharacteristicWriteConfirmationPayload(characteristic.value, status) + CharacteristicWriteConfirmationPayload(characteristic.value) } else { CharacteristicWriteConfirmationError(status) } @@ -107,26 +104,33 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP @Throws(InterruptedException::class, CouldNotConfirmDescriptorWriteException::class) fun confirmWriteDescriptor(descriptorUUID: String, timeout_ms: Int) { - val confirmed = descriptorWriteQueue.poll(timeout_ms.toLong(), TimeUnit.MILLISECONDS) - if (descriptorUUID != confirmed.uuid) { - aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm descriptor write. Got " + confirmed.uuid + ".Expected: " + descriptorUUID + ". Status: " + confirmed.status) - throw CouldNotConfirmDescriptorWriteException(confirmed.uuid!!, descriptorUUID) + val confirmed: DescriptorWriteConfirmation = descriptorWriteQueue.poll(timeout_ms.toLong(), TimeUnit.MILLISECONDS) + ?: throw TimeoutException() + when (confirmed) { + is DescriptorWriteConfirmationError -> throw CouldNotConfirmWriteException(confirmed.status) + is DescriptorWriteConfirmationUUID -> if (confirmed.uuid != descriptorUUID) { + aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm descriptor write. Got ${confirmed.uuid}. Expected: ${descriptorUUID}") + throw CouldNotConfirmDescriptorWriteException(descriptorUUID, confirmed.uuid) + } else { + aapsLogger.debug(LTag.PUMPBTCOMM, "Confirmed descriptor write : " + confirmed.uuid) + } } } override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) { super.onDescriptorWrite(gatt, descriptor, status) - var uuid: String? = null - if (status == BluetoothGatt.GATT_SUCCESS) { - uuid = descriptor.uuid.toString() + val writeConfirmation = if (status == BluetoothGatt.GATT_SUCCESS) { + aapsLogger.debug(LTag.PUMPBTCOMM, "OnDescriptor value " + descriptor.value) + DescriptorWriteConfirmationUUID(descriptor.uuid.toString()) + } else { + DescriptorWriteConfirmationError(status) } - val confirmation = DescriptorWriteConfirmation(status, uuid) try { if (descriptorWriteQueue.size > 0) { aapsLogger.warn(LTag.PUMPBTCOMM, "Descriptor write queue should be empty, found: " + descriptorWriteQueue.size) descriptorWriteQueue.clear() } - val offered = descriptorWriteQueue.offer(confirmation, WRITE_CONFIRM_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS) + val offered = descriptorWriteQueue.offer(writeConfirmation, WRITE_CONFIRM_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS) if (!offered) { aapsLogger.warn(LTag.PUMPBTCOMM, "Received delayed descriptor write confirmation") } @@ -136,7 +140,6 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP } companion object { - - private const val WRITE_CONFIRM_TIMEOUT_MS = 10 // the other thread should be waiting for the exchange + private const val WRITE_CONFIRM_TIMEOUT_MS = 10 // the confirmation queue should be empty anyway } } \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.kt index f863fa29ec2..31e35950508 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/CharacteristicWriteConfirmation.kt @@ -2,6 +2,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbac sealed class CharacteristicWriteConfirmation -class CharacteristicWriteConfirmationPayload(val payload: ByteArray, val status: Int) : CharacteristicWriteConfirmation() +data class CharacteristicWriteConfirmationPayload(val payload: ByteArray) : CharacteristicWriteConfirmation() -class CharacteristicWriteConfirmationError(val status: Int) : CharacteristicWriteConfirmation() \ No newline at end of file +data class CharacteristicWriteConfirmationError(val status: Int) : CharacteristicWriteConfirmation() \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.kt index c975393d7cb..3c7b4f4f9f6 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/DescriptorWriteConfirmation.kt @@ -1,3 +1,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks -class DescriptorWriteConfirmation(var status: Int, var uuid: String?) \ No newline at end of file +sealed class DescriptorWriteConfirmation + +data class DescriptorWriteConfirmationUUID(val uuid: String): DescriptorWriteConfirmation() + +data class DescriptorWriteConfirmationError(val status: Int): DescriptorWriteConfirmation() \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.kt index d5483f3d37c..47389b0a05f 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommand.kt @@ -2,7 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command abstract class BleCommand { - private val data: ByteArray + val data: ByteArray constructor(type: BleCommandType) { data = byteArrayOf(type.value) @@ -14,8 +14,4 @@ abstract class BleCommand { data[0] = type.value System.arraycopy(payload, 0, data, 1, payload.size) } - - fun asByteArray(): ByteArray { - return data - } } \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.kt index 0b49f749705..2bc86e92a77 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmDescriptorWriteException.kt @@ -1,3 +1,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions -class CouldNotConfirmDescriptorWriteException(private val received: String, private val expected: String) : Exception() \ No newline at end of file +class CouldNotConfirmDescriptorWriteException(override val message: String?) : Exception(message) { + constructor(sent: String, confirmed: String): this("Could not confirm write. Sent: {$sent} .Received: ${confirmed}") + constructor(status: Int): this("Could not confirm write. Write status: ${status}") +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.kt deleted file mode 100644 index ab972d4344b..00000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWrite.kt +++ /dev/null @@ -1,3 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions - -class CouldNotConfirmWrite(private val sent: ByteArray, private val confirmed: ByteArray?) : Exception() \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWriteException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWriteException.kt new file mode 100644 index 00000000000..a3c15bfb05a --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/CouldNotConfirmWriteException.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions + +class CouldNotConfirmWriteException(override val message: String?) : Exception(message) { + constructor(sent: ByteArray, confirmed: ByteArray): this("Could not confirm write. Sent: {$sent} .Received: ${confirmed}") + constructor(status: Int): this("Could not confirm write. Write status: ${status}") +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.kt index 9b8ff7488d1..f7f6b08630e 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/exceptions/DiscoveredInvalidPodException.kt @@ -2,4 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.excepti import android.os.ParcelUuid -class DiscoveredInvalidPodException(message: String, serviceUUIds: List) : Exception("$message service UUIDs: $serviceUUIds") \ No newline at end of file +class DiscoveredInvalidPodException: Exception { + constructor(message: String) : super(message) {} + constructor(message: String, serviceUUIds: List) : super("$message service UUIDs: $serviceUUIds"){} +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt index 397520820ca..39cca93aea3 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/io/BleIO.kt @@ -41,7 +41,7 @@ class BleIO(private val aapsLogger: AAPSLogger, private val chars: Map Date: Thu, 25 Feb 2021 19:19:06 +0100 Subject: [PATCH 6/6] ble: address review comments: renames and removed unused vars --- .../dash/driver/comm/CharacteristicType.kt | 2 +- .../dash/driver/comm/ServiceDiscoverer.kt | 5 ++- .../driver/comm/command/BleCommandType.kt | 1 + .../driver/comm/scan/BleDiscoveredDevice.kt | 32 +++++++++---------- .../dash/driver/comm/scan/ScanCollector.kt | 1 - 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt index a68ccba4483..c241a6f43bf 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/CharacteristicType.kt @@ -6,7 +6,7 @@ import java.util.* enum class CharacteristicType(val value: String) { CMD("1a7e2441-e3ed-4464-8b7e-751e03d0dc5f"), DATA("1a7e2442-e3ed-4464-8b7e-751e03d0dc5f"); - val uUID: UUID + val uuid: UUID get() = UUID( BigInteger(value.replace("-", "").substring(0, 16), 16).toLong(), BigInteger(value.replace("-", "").substring(16), 16).toLong() diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt index ccf7298a6e1..997a3ee1cf6 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt @@ -4,7 +4,6 @@ import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.CharacteristicType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CharacteristicNotFoundException import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ServiceNotFoundException @@ -24,9 +23,9 @@ class ServiceDiscoverer(private val logger: AAPSLogger, private val gatt: Blueto logger.debug(LTag.PUMPBTCOMM, "Services discovered") val service = gatt.getService(SERVICE_UUID.toUuid()) ?: throw ServiceNotFoundException(SERVICE_UUID) - val cmdChar = service.getCharacteristic(CharacteristicType.CMD.uUID) + val cmdChar = service.getCharacteristic(CharacteristicType.CMD.uuid) ?: throw CharacteristicNotFoundException(CharacteristicType.CMD.value) - val dataChar = service.getCharacteristic(CharacteristicType.DATA.uUID) // TODO: this is never used + val dataChar = service.getCharacteristic(CharacteristicType.DATA.uuid) // TODO: this is never used ?: throw CharacteristicNotFoundException(CharacteristicType.DATA.value) var chars = mapOf(CharacteristicType.CMD to cmdChar, CharacteristicType.DATA to dataChar) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.kt index ad3cb86fe2f..9fb461b02de 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/command/BleCommandType.kt @@ -5,6 +5,7 @@ enum class BleCommandType(val value: Byte) { companion object { + @JvmStatic fun byValue(value: Byte): BleCommandType = BleCommandType.values().firstOrNull { it.value == value } ?: throw IllegalArgumentException("Unknown BleCommandType: $value") diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.kt index af6275cd6a2..64e04630a08 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/BleDiscoveredDevice.kt @@ -4,7 +4,7 @@ import android.bluetooth.le.ScanResult import android.os.ParcelUuid import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.DiscoveredInvalidPodException -class BleDiscoveredDevice(val scanResult: ScanResult, private val podID: Long) { +class BleDiscoveredDevice(val scanResult: ScanResult, private val podId: Long) { private val sequenceNo: Int private val lotNo: Long @@ -12,29 +12,29 @@ class BleDiscoveredDevice(val scanResult: ScanResult, private val podID: Long) { private fun validateServiceUUIDs() { val scanRecord = scanResult.scanRecord ?: throw DiscoveredInvalidPodException("Scan record is null"); - val serviceUUIDs = scanRecord.serviceUuids - if (serviceUUIDs.size != 9) { - throw DiscoveredInvalidPodException("Expected 9 service UUIDs, got" + serviceUUIDs.size, serviceUUIDs) + val serviceUuids = scanRecord.serviceUuids + if (serviceUuids.size != 9) { + throw DiscoveredInvalidPodException("Expected 9 service UUIDs, got" + serviceUuids.size, serviceUuids) } - if (extractUUID16(serviceUUIDs[0]) != "4024") { + if (extractUUID16(serviceUuids[0]) != MAIN_SERVICE_UUID) { // this is the service that we filtered for - throw DiscoveredInvalidPodException("The first exposed service UUID should be 4024, got " + extractUUID16(serviceUUIDs[0]), serviceUUIDs) + throw DiscoveredInvalidPodException("The first exposed service UUID should be 4024, got " + extractUUID16(serviceUuids[0]), serviceUuids) } // TODO understand what is serviceUUIDs[1]. 0x2470. Alarms? - if (extractUUID16(serviceUUIDs[2]) != "000a") { + if (extractUUID16(serviceUuids[2]) != "000a") { // constant? - throw DiscoveredInvalidPodException("The third exposed service UUID should be 000a, got " + serviceUUIDs[2], serviceUUIDs) + throw DiscoveredInvalidPodException("The third exposed service UUID should be 000a, got " + serviceUuids[2], serviceUuids) } } @Throws(DiscoveredInvalidPodException::class) - private fun validatePodID() { + private fun validatePodId() { val scanRecord = scanResult.scanRecord val serviceUUIDs = scanRecord.serviceUuids - val hexPodID = extractUUID16(serviceUUIDs[3]) + extractUUID16(serviceUUIDs[4]) - val podID = hexPodID.toLong(16) - if (this.podID != podID) { - throw DiscoveredInvalidPodException("This is not the POD we are looking for. " + this.podID + " found: " + podID, serviceUUIDs) + val hexPodId = extractUUID16(serviceUUIDs[3]) + extractUUID16(serviceUUIDs[4]) + val podId = hexPodId.toLong(16) + if (this.podId != podId) { + throw DiscoveredInvalidPodException("This is not the POD we are looking for. " + this.podId + " found: " + this.podId, serviceUUIDs) } } @@ -58,14 +58,14 @@ class BleDiscoveredDevice(val scanResult: ScanResult, private val podID: Long) { override fun toString(): String { return "BleDiscoveredDevice{" + "scanResult=" + scanResult + - ", podID=" + podID + + ", podID=" + podId + ", sequenceNo=" + sequenceNo + ", lotNo=" + lotNo + '}' } companion object { - + const val MAIN_SERVICE_UUID = "4024"; private fun extractUUID16(uuid: ParcelUuid): String { return uuid.toString().substring(4, 8) } @@ -73,7 +73,7 @@ class BleDiscoveredDevice(val scanResult: ScanResult, private val podID: Long) { init { validateServiceUUIDs() - validatePodID() + validatePodId() lotNo = parseLotNo() sequenceNo = parseSeqNo() } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt index 11648159707..0030c755ebd 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/scan/ScanCollector.kt @@ -21,7 +21,6 @@ class ScanCollector(private val logger: AAPSLogger, private val podID: Long) : S } override fun onScanFailed(errorCode: Int) { - scanFailed = errorCode logger.warn(LTag.PUMPBTCOMM, "Scan failed with errorCode: $errorCode") super.onScanFailed(errorCode) }