Skip to content

Commit

Permalink
Android source: Prepare for the 3.2.10 release
Browse files Browse the repository at this point in the history
  • Loading branch information
JOikarinen committed Apr 7, 2022
1 parent da8f3ee commit 9383706
Show file tree
Hide file tree
Showing 21 changed files with 373 additions and 119 deletions.
2 changes: 1 addition & 1 deletion sources/Android/android-communications/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.6.10'
ext.kotlin_version = '1.6.20'
ext.protobuf_version = '0.8.12'
ext.dokka_version = '1.4.32'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ dependencies {
implementation 'androidx.annotation:annotation:1.3.0'
implementation "androidx.core:core-ktx:1.7.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
sdkImplementation 'com.google.protobuf:protobuf-javalite:3.17.3'
sdkImplementation 'com.google.protobuf:protobuf-javalite:3.19.2'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-core:4.3.1'
testImplementation 'io.mockk:mockk:1.12.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,24 +388,21 @@ public Completable waitNotificationEnabled(final UUID uuid, final boolean checkC
if (integer.get() == ATT_SUCCESS) {
emitter.onComplete();
return;
}
synchronized (integer) {
if (integer.get() == ATT_SUCCESS) {
emitter.onComplete();
return;
} else if (integer.get() != -1) {
throw new BleAttributeError("Failed to set characteristic notification or indication ", integer.get());
} else if (integer.get() != -1) {
throw new BleAttributeError("Failed to set characteristic notification or indication ", integer.get());
} else {
synchronized (integer) {
integer.wait();
}
integer.wait();
if (integer.get() != ATT_SUCCESS && !emitter.isDisposed()) {
if (integer.get() != -1) {
throw new BleAttributeError("Failed to set characteristic notification or indication ", integer.get());
} else {
throw new BleDisconnected();
}
}
emitter.onComplete();
}
emitter.onComplete();
} else {
throw new BleCharacteristicNotFound();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
* Note any of these functions might be called from different thread
*/
public interface BleGattTxInterface {
void transmitMessages(BleGattBase gattServiceBase, UUID serviceUuid, UUID characteristicUuid, List<byte[]> packets, boolean withResponse) throws Exception;
void transmitMessages(UUID serviceUuid, UUID characteristicUuid, List<byte[]> packets, boolean withResponse) throws Exception;

void transmitMessage(BleGattBase gattServiceBase, UUID serviceUuid, UUID characteristicUuid, byte[] packet, boolean withResponse) throws Exception;
void transmitMessage(UUID serviceUuid, UUID characteristicUuid, byte[] packet, boolean withResponse) throws Exception;

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

void setCharacteristicNotify(BleGattBase gattServiceBase, UUID serviceUuid, UUID characteristicUuid, boolean enable) throws BleCharacteristicNotFound, BleServiceNotFound, BleGattNotInitialized;
void setCharacteristicNotify(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 @@ -120,7 +120,7 @@ String toString() {
}

private byte[] readSettingsValue() throws Exception {
txInterface.readValue(BleH7SettingsClient.this, H7_SETTINGS_SERVICE, H7_SETTINGS_CHARACTERISTIC);
txInterface.readValue(H7_SETTINGS_SERVICE, H7_SETTINGS_CHARACTERISTIC);
byte[] packet = h7InputQueue.poll(30, TimeUnit.SECONDS);
if (packet != null) {
return packet;
Expand Down Expand Up @@ -164,8 +164,7 @@ public Single<H7SettingsResponse> sendSettingsCommand(final H7SettingsMessage co
} else {
values[0] = (byte) ((parameter << 1) | broadcastValue);
}
txInterface.transmitMessages(BleH7SettingsClient.this,
H7_SETTINGS_SERVICE,
txInterface.transmitMessages(H7_SETTINGS_SERVICE,
H7_SETTINGS_CHARACTERISTIC,
Collections.singletonList(values), true);
Integer error = h7WrittenQueue.poll(30, TimeUnit.SECONDS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,13 @@ public Flowable<HrNotificationData> observeHrNotifications(final boolean checkCo
.startWith(Completable.fromAction(() -> {
BleLogger.d(TAG, "Start observing HR");
addCharacteristicNotification(HR_MEASUREMENT);
getTxInterface().setCharacteristicNotify(this, HR_SERVICE, HR_MEASUREMENT, true);
getTxInterface().setCharacteristicNotify(HR_SERVICE, HR_MEASUREMENT, true);
}))
.doFinally(() -> {
BleLogger.d(TAG, "Stop observing HR");
removeCharacteristicNotification(HR_MEASUREMENT);
try {
getTxInterface().setCharacteristicNotify(this, HR_SERVICE, HR_MEASUREMENT, false);
getTxInterface().setCharacteristicNotify(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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,7 @@ String toString() {
}

private PfcResponse sendPfcCommandAndProcessResponse(byte[] packet) throws Exception {
txInterface.transmitMessages(BlePfcClient.this, PFC_SERVICE, PFC_CP,
Collections.singletonList(packet), true);
txInterface.transmitMessages(PFC_SERVICE, PFC_CP, Collections.singletonList(packet), true);
Pair<byte[], Integer> pair = pfcCpInputQueue.poll(30, TimeUnit.SECONDS);
if (pair != null) {
if (pair.second == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ public class BlePsdClient extends BleGattBase {
public static final byte OPERATION_FAILED = 0x04;
public static final byte NOT_ALLOWED = 0x05;


public static final UUID PSD_SERVICE = UUID.fromString("FB005C20-02E7-F387-1CAD-8ACD2D8DF0C8");
public static final UUID PSD_FEATURE = UUID.fromString("FB005C21-02E7-F387-1CAD-8ACD2D8DF0C8");
public static final UUID PSD_CP = UUID.fromString("FB005C22-02E7-F387-1CAD-8ACD2D8DF0C8");
Expand Down Expand Up @@ -276,7 +275,7 @@ String toString() {
}

private PsdResponse sendPsdCommandAndProcessResponse(byte[] packet) throws Exception {
txInterface.transmitMessages(BlePsdClient.this, PSD_SERVICE, PSD_CP, Arrays.asList(packet), true);
txInterface.transmitMessages(PSD_SERVICE, PSD_CP, Arrays.asList(packet), true);
Pair<byte[], Integer> pair = psdCpInputQueue.poll(30, TimeUnit.SECONDS);
if (pair != null) {
if (pair.second == 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ class BlePMDClient(txInterface: BleGattTxInterface) : BleGattBase(txInterface, P
TYPE_4(4),
TYPE_5(5),
TYPE_6(6),
TYPE_7(7);
TYPE_7(7),
TYPE_8(8);

companion object {
fun getTypeById(id: Int): PmdDataFrameType {
Expand Down Expand Up @@ -213,7 +214,7 @@ class BlePMDClient(txInterface: BleGattTxInterface) : BleGattBase(txInterface, P

@Throws(Exception::class)
private fun sendPmdCommand(packet: ByteArray): PmdControlPointResponse {
txInterface.transmitMessage(this@BlePMDClient, PMD_SERVICE, PMD_CP, packet, true)
txInterface.transmitMessage(PMD_SERVICE, PMD_CP, packet, true)
val first = receiveControlPointPacket()
val response = PmdControlPointResponse(first)
var more = response.more
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,42 @@
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.PmdDataFrameType
import com.polar.androidcommunications.api.ble.model.gatt.client.pmd.BlePMDClientUtils
import com.polar.androidcommunications.common.ble.BleUtils
import java.util.*

sealed class EcgDataSample

class EcgData internal constructor(@JvmField val timeStamp: Long) {

data class EcgSample internal constructor(
// samples in signed microvolts
val timeStamp: Long,

@JvmField
val microVolts: Int,
val overSampling: Boolean = false,
val skinContactBit: Byte = 0,
val contactImpedance: Byte = 0,
val ecgDataTag: Byte = 0,
val paceDataTag: Byte = 0,
)
) : EcgDataSample()

data class EcgSampleFrameType3 internal constructor(
val data0: Int,
val data1: Int,
val status: UByte
) : EcgDataSample()

@JvmField
val ecgSamples: MutableList<EcgSample> = ArrayList()
val ecgSamples: MutableList<EcgDataSample> = ArrayList()

companion object {
fun parseDataFromDataFrame(isCompressed: Boolean, frameType: PmdDataFrameType, frame: ByteArray, factor: Float, timeStamp: Long): EcgData {
fun parseDataFromDataFrame(isCompressed: Boolean, frameType: PmdDataFrameType, frame: ByteArray, factor: Float = 1.0f, timeStamp: Long): EcgData {
return if (isCompressed) {
throw java.lang.Exception("Compressed FrameType: $frameType is not supported by EcgData data parser")
} else {
when (frameType) {
PmdDataFrameType.TYPE_0 -> dataFromRawType0(frame, timeStamp)
PmdDataFrameType.TYPE_1 -> dataFromRawType1(frame, timeStamp)
PmdDataFrameType.TYPE_2 -> dataFromRawType2(frame, timeStamp)
PmdDataFrameType.TYPE_3 -> dataFromRawType3(frame, timeStamp)
else -> throw java.lang.Exception("Raw FrameType: $frameType is not supported by EcgData data parser")
}
}
Expand All @@ -43,7 +48,7 @@ class EcgData internal constructor(@JvmField val timeStamp: Long) {
while (offset < value.size) {
val microVolts = BleUtils.convertArrayToSignedInt(value, offset, 3)
offset += 3
ecgData.ecgSamples.add(EcgSample(timeStamp = timeStamp, microVolts = microVolts))
ecgData.ecgSamples.add(EcgSample(microVolts = microVolts))
}
return ecgData
}
Expand All @@ -59,7 +64,6 @@ class EcgData internal constructor(@JvmField val timeStamp: Long) {
offset += 3
ecgData.ecgSamples.add(
EcgSample(
timeStamp = timeStamp,
microVolts = microVolts,
overSampling = overSampling,
skinContactBit = skinContactBit,
Expand All @@ -80,7 +84,6 @@ class EcgData internal constructor(@JvmField val timeStamp: Long) {
offset += 3
ecgData.ecgSamples.add(
EcgSample(
timeStamp = timeStamp,
microVolts = microVolts,
ecgDataTag = ecgDataTag,
paceDataTag = paceDataTag
Expand All @@ -89,5 +92,27 @@ class EcgData internal constructor(@JvmField val timeStamp: Long) {
}
return ecgData
}

private fun dataFromRawType3(frame: ByteArray, timeStamp: Long): EcgData {
val ecgData = EcgData(timeStamp)
var offset = 0
while (offset < frame.size) {
val data0 = BlePMDClientUtils.parseFrameDataField(frame.sliceArray(offset..(offset + 2)), BlePMDClient.PmdDataFieldEncoding.SIGNED_INT) as Int
offset += 3
val data1 = BlePMDClientUtils.parseFrameDataField(frame.sliceArray(offset..(offset + 2)), BlePMDClient.PmdDataFieldEncoding.SIGNED_INT) as Int
offset += 3
val status = BlePMDClientUtils.parseFrameDataField(frame.sliceArray(offset..offset), BlePMDClient.PmdDataFieldEncoding.UNSIGNED_BYTE) as UByte
offset += 1

ecgData.ecgSamples.add(
EcgSampleFrameType3(
data0 = data0,
data1 = data1,
status = status,
)
)
}
return ecgData
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ 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.BlePMDClientUtils
import com.polar.androidcommunications.common.ble.BleUtils
import java.util.*
import kotlin.experimental.and

/**
Expand All @@ -25,6 +24,12 @@ class PpgData internal constructor(val timeStamp: Long) {
val status: UInt
) : PpgDataSample()

// PPG Data Sample 3
data class PpgDataSampleType3 internal constructor(
val ppgDataSamples: List<Int>,
val status: UInt
) : PpgDataSample()

// PPG Data frame type 4
data class PpgDataSampleFrameType4 internal constructor(
val numIntTs: List<UInt>,
Expand All @@ -51,6 +56,7 @@ class PpgData internal constructor(val timeStamp: Long) {
when (frameType) {
BlePMDClient.PmdDataFrameType.TYPE_0 -> dataFromCompressedType0(frame, factor, timeStamp)
BlePMDClient.PmdDataFrameType.TYPE_7 -> dataFromCompressedType7(frame, factor, timeStamp)
BlePMDClient.PmdDataFrameType.TYPE_8 -> dataFromCompressedType8(frame, factor, timeStamp)
else -> throw java.lang.Exception("Compressed FrameType: $frameType is not supported by PPG data parser")
}
} else {
Expand Down Expand Up @@ -140,11 +146,25 @@ class PpgData internal constructor(val timeStamp: Long) {
val channels = sample.subList(0, 16).map {
if (factor != 1.0f) (it.toFloat() * factor).toInt() else it
}
val status = sample[16].toUInt()
val status = (sample[16] and 0xFFFFFF).toUInt()

ppgData.ppgSamples.add(PpgDataSampleType2(ppgDataSamples = channels, status))
}
return ppgData
}

private fun dataFromCompressedType8(value: ByteArray, factor: Float, timeStamp: Long): PpgData {
val samples = BlePMDClient.parseDeltaFramesAll(value, 25, 24, BlePMDClient.PmdDataFieldEncoding.SIGNED_INT)
val ppgData = PpgData(timeStamp)
for (sample in samples) {
val channels = sample.subList(0, 24).map {
if (factor != 1.0f) (it.toFloat() * factor).toInt() else it
}
val status = (sample[24] and 0xFFFFFF).toUInt()

ppgData.ppgSamples.add(PpgDataSampleType3(ppgDataSamples = channels, status))
}
return ppgData
}
}
}
Loading

0 comments on commit 9383706

Please sign in to comment.