Skip to content

Commit

Permalink
Issue #209: Fixed. api.shutDown did not correctly release it resources.
Browse files Browse the repository at this point in the history
  • Loading branch information
JOikarinen committed Nov 5, 2021
1 parent 9e2ac33 commit 8176a4a
Show file tree
Hide file tree
Showing 27 changed files with 890 additions and 690 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ protobuf {

dependencies {
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'io.reactivex.rxjava3:rxjava:3.0.4'
implementation 'io.reactivex.rxjava3:rxjava:3.1.1'
implementation 'commons-io:commons-io:2.10.0'
implementation 'androidx.annotation:annotation:1.2.0'
implementation "androidx.core:core-ktx:1.6.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.polar.androidcommunications.api.ble.exceptions

/**
* Error indicating the device is not supporting BLE
*/
class BleNotAvailableInDevice(message: String) : Exception(message)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.polar.androidcommunications.api.ble.exceptions

class BleStartScanError(message: String, val error: Int) : Exception("$message failed with error: $error")
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.polar.androidcommunications.api.ble.model.advertisement;

import static com.polar.androidcommunications.api.ble.model.polar.PolarAdvDataUtility.getPolarModelNameFromAdvLocalName;
import static com.polar.androidcommunications.api.ble.model.polar.PolarAdvDataUtility.isPolarDevice;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

Expand All @@ -12,9 +15,6 @@
import java.util.List;
import java.util.Objects;

import static com.polar.androidcommunications.api.ble.model.polar.PolarAdvDataUtility.getPolarModelNameFromAdvLocalName;
import static com.polar.androidcommunications.api.ble.model.polar.PolarAdvDataUtility.isPolarDevice;


public class BleAdvertisementContent {
public static final String BLE_ADV_POLAR_PREFIX_IN_LOCAL_NAME = "Polar";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.polar.androidcommunications.api.ble.model.gatt;

import com.polar.androidcommunications.api.ble.exceptions.BleCharacteristicNotFound;
import com.polar.androidcommunications.api.ble.exceptions.BleGattNotInitialized;
import com.polar.androidcommunications.api.ble.exceptions.BleServiceNotFound;

import java.util.List;
import java.util.UUID;

Expand All @@ -13,7 +17,7 @@ public interface BleGattTxInterface {

void readValue(BleGattBase gattServiceBase, UUID serviceUuid, UUID characteristicUuid) throws Exception;

void setCharacteristicNotify(BleGattBase gattServiceBase, UUID serviceUuid, UUID characteristicUuid, boolean enable) throws Exception;
void setCharacteristicNotify(BleGattBase gattServiceBase, UUID serviceUuid, UUID characteristicUuid, boolean enable) throws BleCharacteristicNotFound, BleServiceNotFound, BleGattNotInitialized;

boolean isConnected(); // for client

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,12 @@ public Flowable<HrNotificationData> observeHrNotifications(final boolean checkCo
.doFinally(() -> {
BleLogger.d(TAG, "Stop observing HR");
removeCharacteristicNotification(HR_MEASUREMENT);
getTxInterface().setCharacteristicNotify(this, HR_SERVICE, HR_MEASUREMENT, false);
try {
getTxInterface().setCharacteristicNotify(this, HR_SERVICE, HR_MEASUREMENT, false);
} catch (Exception e) {
// this may happen if connection is already closed, no need sent the exception to downstream
BleLogger.d(TAG, "HR client is not able to set characteristic notify to false. Reason " + e.toString());
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import kotlin.math.ceil

/**
* BLE Client for Polar Measurement Data Service (aka. PMD service)
* */
* BLE Client for Polar Measurement Data Service (aka. PMD service)
* */
class BlePMDClient(txInterface: BleGattTxInterface) : BleGattBase(txInterface, PMD_SERVICE) {
private val pmdCpInputQueue = LinkedBlockingQueue<Pair<ByteArray, Int>>()
private val ecgObservers = AtomicSet<FlowableEmitter<in EcgData>>()
Expand All @@ -35,6 +36,7 @@ class BlePMDClient(txInterface: BleGattTxInterface) : BleGattBase(txInterface, P
private val ppiObservers = AtomicSet<FlowableEmitter<in PpiData>>()
private val pressureObservers = AtomicSet<FlowableEmitter<in PressureData>>()
private val locationObservers = AtomicSet<FlowableEmitter<in GnssLocationData>>()
private val temperatureObservers = AtomicSet<FlowableEmitter<in TemperatureData>>()
private val rdObservers = AtomicSet<FlowableEmitter<in ByteArray>>()
private var pmdFeatureData: ByteArray? = null
private val controlPointMutex = Object()
Expand Down Expand Up @@ -95,7 +97,7 @@ class BlePMDClient(txInterface: BleGattTxInterface) : BleGattBase(txInterface, P
val ieee754 = it
return java.lang.Float.intBitsToFloat(ieee754)
}
BleLogger.e(TAG, "No factor found for type: $type")
BleLogger.w(TAG, "No factor found for type: $type")
return 1.0f
}

Expand Down Expand Up @@ -169,6 +171,13 @@ class BlePMDClient(txInterface: BleGattTxInterface) : BleGattBase(txInterface, P
emitter.onNext(GnssLocationData.parseDataFromDataFrame(isCompressedFrameType, frameType, content, factor, timeStamp))
}
}
PmdMeasurementType.TEMPERATURE -> {
val factor = fetchFactor(PmdMeasurementType.TEMPERATURE)
RxUtils.emitNext(temperatureObservers) { emitter: FlowableEmitter<in TemperatureData> ->
emitter.onNext(TemperatureData.parseDataFromDataFrame(isCompressedFrameType, frameType, content, factor, timeStamp))
}
}

else -> {
val rdData = ByteArray(data.size - 1)
System.arraycopy(data, 1, content, 0, content.size)
Expand Down Expand Up @@ -423,6 +432,10 @@ class BlePMDClient(txInterface: BleGattTxInterface) : BleGattBase(txInterface, P
return RxUtils.monitorNotifications(locationObservers, txInterface, checkConnection)
}

fun monitorTemperatureNotifications(checkConnection: Boolean): Flowable<TemperatureData> {
return RxUtils.monitorNotifications(temperatureObservers, txInterface, checkConnection)
}

override fun clientReady(checkConnection: Boolean): Completable {
return Completable.concatArray(
waitNotificationEnabled(PMD_CP, true),
Expand Down Expand Up @@ -453,6 +466,7 @@ class BlePMDClient(txInterface: BleGattTxInterface) : BleGattBase(txInterface, P
RxUtils.postExceptionAndClearList(magnetometerObservers, throwable)
RxUtils.postExceptionAndClearList(pressureObservers, throwable)
RxUtils.postExceptionAndClearList(locationObservers, throwable)
RxUtils.postExceptionAndClearList(temperatureObservers, throwable)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ class PmdFeature(data: ByteArray) {
@JvmField
val magnetometerSupported: Boolean = (data[1].toUInt() and 0x40u) != 0u

@JvmField
val locationSupported: Boolean = (data[2].toUInt() and 0x04u) != 0u

@JvmField
val barometerSupported: Boolean = (data[2].toUInt() and 0x08u) != 0u

@JvmField
val locationSupported: Boolean = (data[2].toUInt() and 0x04u) != 0u
val temperatureSupported: Boolean = (data[2].toUInt() and 0x10u) != 0u

@JvmField
val sdkModeSupported: Boolean = (data[2].toUInt() and 0x02u) != 0u
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ enum class PmdMeasurementType(val numVal: Int) {
SDK_MODE(9),
LOCATION(10),
PRESSURE(11),
TEMPERATURE(12),
UNKNOWN_TYPE(0xff);

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.polar.androidcommunications.api.ble.model.gatt.client.pmd.model

import com.polar.androidcommunications.api.ble.BleLogger
import com.polar.androidcommunications.api.ble.model.gatt.client.pmd.BlePMDClient
import com.polar.androidcommunications.api.ble.model.gatt.client.pmd.BlePMDClientUtils
import com.polar.androidcommunications.common.ble.BleUtils
Expand Down Expand Up @@ -83,7 +82,6 @@ class PpgData internal constructor(val timeStamp: Long) {
var dataType4Counter = 0
private fun dataFromRawType4(frame: ByteArray, timeStamp: Long): PpgData {
dataType4Counter++
BleLogger.d("TESTING", "PPG Data4 received. Counter: $dataType4Counter timeStamp: $timeStamp")

val ppgData = PpgData(timeStamp)
var offset = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.polar.androidcommunications.api.ble.model.gatt.client.pmd.model

import com.polar.androidcommunications.api.ble.model.gatt.client.pmd.BlePMDClient
import com.polar.androidcommunications.api.ble.model.gatt.client.pmd.BlePMDClient.PmdDataFieldEncoding
import com.polar.androidcommunications.api.ble.model.gatt.client.pmd.BlePMDClientUtils
import java.lang.Float.intBitsToFloat
import java.util.*

Expand All @@ -23,15 +24,18 @@ class PressureData internal constructor(val timeStamp: Long) {
fun parseDataFromDataFrame(isCompressed: Boolean, frameType: BlePMDClient.PmdDataFrameType, frame: ByteArray, factor: Float, timeStamp: Long): PressureData {
return if (isCompressed) {
when (frameType) {
BlePMDClient.PmdDataFrameType.TYPE_0 -> dataFromType0(frame, factor, timeStamp)
BlePMDClient.PmdDataFrameType.TYPE_0 -> dataFromCompressedType0(frame, factor, timeStamp)
else -> throw java.lang.Exception("Compressed FrameType: $frameType is not supported by Pressure data parser")
}
} else {
throw java.lang.Exception("Raw FrameType: $frameType is not supported by Pressure data parser")
when (frameType) {
BlePMDClient.PmdDataFrameType.TYPE_0 -> dataFromRawType0(frame, timeStamp)
else -> throw java.lang.Exception("Raw FrameType: $frameType is not supported by Pressure data parser")
}
}
}

private fun dataFromType0(frame: ByteArray, factor: Float, timeStamp: Long): PressureData {
private fun dataFromCompressedType0(frame: ByteArray, factor: Float, timeStamp: Long): PressureData {
val samples = BlePMDClient.parseDeltaFramesAll(frame, 1, 32, PmdDataFieldEncoding.FLOAT_IEEE754)
val pressureData = PressureData(timeStamp)
for (sample in samples) {
Expand All @@ -40,5 +44,17 @@ class PressureData internal constructor(val timeStamp: Long) {
}
return pressureData
}

private fun dataFromRawType0(frame: ByteArray, timeStamp: Long): PressureData {
val pressureData = PressureData(timeStamp)
var offset = 0

while (offset < frame.size) {
val pressure = BlePMDClientUtils.parseFrameDataField(frame.sliceArray(offset..(offset + 3)), PmdDataFieldEncoding.FLOAT_IEEE754) as Float
offset += 4
pressureData.pressureSamples.add(PressureSample(pressure))
}
return pressureData
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.polar.androidcommunications.api.ble.model.gatt.client.pmd.model

import com.polar.androidcommunications.api.ble.model.gatt.client.pmd.BlePMDClient
import com.polar.androidcommunications.api.ble.model.gatt.client.pmd.BlePMDClient.PmdDataFieldEncoding
import com.polar.androidcommunications.api.ble.model.gatt.client.pmd.BlePMDClientUtils
import java.lang.Float.intBitsToFloat
import java.util.*

/**
* Temperature data
* @param timeStamp ns in epoch time. The time stamp represent time of last sample in [temperatureSamples] list
*/
class TemperatureData internal constructor(val timeStamp: Long) {

data class TemperatureSample internal constructor(
// Sample contains signed temperature value in celcius
val temperature: Float
)

@JvmField
val temperatureSamples: MutableList<TemperatureSample> = ArrayList()

companion object {
fun parseDataFromDataFrame(isCompressed: Boolean, frameType: BlePMDClient.PmdDataFrameType, frame: ByteArray, factor: Float, timeStamp: Long): TemperatureData {
return if (isCompressed) {
when (frameType) {
BlePMDClient.PmdDataFrameType.TYPE_0 -> dataFromCompressedType0(frame, factor, timeStamp)
else -> throw java.lang.Exception("Compressed FrameType: $frameType is not supported by Temperature data parser")
}
} else {
when (frameType) {
BlePMDClient.PmdDataFrameType.TYPE_0 -> dataFromRawType0(frame, timeStamp)
else -> throw java.lang.Exception("Raw FrameType: $frameType is not supported by Temperature data parser")
}
}
}

private fun dataFromCompressedType0(frame: ByteArray, factor: Float, timeStamp: Long): TemperatureData {
val samples = BlePMDClient.parseDeltaFramesAll(frame, 1, 32, PmdDataFieldEncoding.FLOAT_IEEE754)
val temperatureData = TemperatureData(timeStamp)
for (sample in samples) {
val pressure = if (factor != 1.0f) intBitsToFloat(sample[0]) * factor else intBitsToFloat(sample[0])
temperatureData.temperatureSamples.add(TemperatureSample(pressure))
}
return temperatureData
}

private fun dataFromRawType0(frame: ByteArray, timeStamp: Long): TemperatureData {
val temperatureData = TemperatureData(timeStamp)
var offset = 0

while (offset < frame.size) {
val temperature = BlePMDClientUtils.parseFrameDataField(frame.sliceArray(offset..(offset + 3)), PmdDataFieldEncoding.FLOAT_IEEE754) as Float
offset += 4
temperatureData.temperatureSamples.add(TemperatureSample(temperature))
}
return temperatureData
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface AuthenticationObserverInterface {
void bondNone();
}

private final static String TAG = BDBondingListener.class.getSimpleName();
private static final String TAG = BDBondingListener.class.getSimpleName();
private final Context context;
private final AtomicSet<BondingObserver> authenticationObservers = new AtomicSet<>();

Expand All @@ -38,7 +38,7 @@ void stopBroadcastReceiver() {
}
}

static abstract class BondingObserver implements AuthenticationObserverInterface {
abstract static class BondingObserver implements AuthenticationObserverInterface {
private final BluetoothDevice device;

BondingObserver(BluetoothDevice device) {
Expand Down
Loading

0 comments on commit 8176a4a

Please sign in to comment.