Skip to content

Commit

Permalink
Fix timestamp handling between split files
Browse files Browse the repository at this point in the history
- The last timestamp of the previous file is taken into account to ensure the correct sampling rate when switching files
  • Loading branch information
Samuli Määttä committed Jan 3, 2024
1 parent a31b110 commit e2d69bd
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 64 deletions.
2 changes: 1 addition & 1 deletion PolarBleSdk.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'PolarBleSdk'
s.version = '5.6.0-beta1'
s.version = '5.6.0-beta2'
s.summary = 'SDK for Polar sensors'
s.homepage = 'https://github.com/polarofficial/polar-ble-sdk'
s.license = { :type => 'Custom', :file => 'Polar_SDK_License.txt' }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ internal class OfflineRecordingData<out T>(
private const val PACKET_SIZE_LENGTH = 2

@Throws(Exception::class)
fun parseDataFromOfflineFile(fileData: ByteArray, type: PmdMeasurementType, secret: PmdSecret? = null): OfflineRecordingData<Any> {
BleLogger.d(TAG, "Start offline file parsing. File size is ${fileData.size} and type $type")
fun parseDataFromOfflineFile(fileData: ByteArray, type: PmdMeasurementType, secret: PmdSecret? = null, lastTimestamp: ULong = 0uL): OfflineRecordingData<Any> {
BleLogger.d(TAG, "Start offline file parsing. File size is ${fileData.size} and type $type, previous file last timestamp: $lastTimestamp")

// guard
if (fileData.isEmpty()) {
Expand All @@ -70,7 +70,8 @@ internal class OfflineRecordingData<out T>(
val parsedData = parseData(
dataBytes = payloadDataBytes,
metaData = metaData,
builder = getDataBuilder(type)
builder = getDataBuilder(type),
lastTimestamp = lastTimestamp
)

return OfflineRecordingData(
Expand Down Expand Up @@ -271,9 +272,9 @@ internal class OfflineRecordingData<out T>(
return TypeUtils.convertArrayToUnsignedInt(packetSize.toByteArray(), 0, 2)
}

private fun <T> parseData(dataBytes: List<Byte>, metaData: OfflineRecordingMetaData, builder: T): T {
private fun <T> parseData(dataBytes: List<Byte>, metaData: OfflineRecordingMetaData, builder: T, lastTimestamp: ULong = 0uL): T {

var previousTimeStamp: ULong = 0uL
var previousTimeStamp: ULong = lastTimestamp
var packetSize = metaData.dataPayloadSize
val sampleRate = metaData.recordingSettings?.settings?.get(PmdSetting.PmdSettingType.SAMPLE_RATE)?.first() ?: 0
val factor = metaData.recordingSettings?.settings?.get(PmdSetting.PmdSettingType.FACTOR)?.first()?.let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ object PolarBleApiDefaultImpl {
*/
@JvmStatic
fun versionInfo(): String {
return "5.6.0-beta"
return "5.6.0-beta2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1239,32 +1239,33 @@ extension PolarBleApiImpl: PolarBleApi {
var polarPpiData: PolarOfflineRecordingData?
var polarHrData: PolarOfflineRecordingData?

var lastTimestamp: UInt64 = 0
_ = subRecordingCountObservable
.flatMap { count -> Observable<PolarOfflineRecordingData> in
return Observable.range(start: 0, count: count)
.flatMap { subRecordingIndex -> Observable<PolarOfflineRecordingData> in
Observable.create { observer in

let subRecordingPath: String
if entry.path.range(of: ".*\\.REC$", options: .regularExpression) != nil && count > 0 {
subRecordingPath = entry.path.replacingOccurrences(of: "\\d(?=\\.REC$)", with: "\(subRecordingIndex)", options: .regularExpression)
} else {
subRecordingPath = entry.path
}

do {
var operation = Protocol_PbPFtpOperation()
operation.command = Protocol_PbPFtpOperation.Command.get
operation.path = subRecordingPath.isEmpty ? entry.path : subRecordingPath
let request = try operation.serializedData()

BleLogger.trace("Offline record get. Device: \(identifier) Path: \(subRecordingPath) Secret used: \(secret != nil)")

let notificationResult = client.sendNotification(
Protocol_PbPFtpHostToDevNotification.initializeSession.rawValue,
parameters: nil
)

let requestResult = notificationResult
.andThen(Single.deferred { client.request(request) })
.map { dataResult in
Expand All @@ -1273,20 +1274,22 @@ extension PolarBleApiImpl: PolarBleApi {
let offlineRecordingData: OfflineRecordingData = try OfflineRecordingData<Any>.parseDataFromOfflineFile(
fileData: dataResult as Data,
type: PolarDataUtils.mapToPmdClientMeasurementType(from: entry.type),
secret: pmdSecret
secret: pmdSecret,
lastTimestamp: lastTimestamp
)
return offlineRecordingData
} catch {
throw PolarErrors.polarOfflineRecordingError(description: "Failed to parse data")
}
}

_ = requestResult.subscribe(
onSuccess: { offlineRecordingData in
do {
let settings: PolarSensorSetting = offlineRecordingData.recordingSettings?.mapToPolarSettings() ?? PolarSensorSetting()
switch offlineRecordingData.data {
case let accData as AccData:
lastTimestamp = accData.samples.last?.timeStamp ?? 0
switch polarAccData {
case let .accOfflineRecordingData(existingData, startTime, existingSettings):
let newSamples = existingData.samples + accData.samples.map { (timeStamp: $0.timeStamp, x: $0.x, y: $0.y, z: $0.z) }
Expand All @@ -1305,6 +1308,7 @@ extension PolarBleApiImpl: PolarBleApi {
observer.onNext(polarAccData!)
}
case let gyroData as GyrData:
lastTimestamp = gyroData.samples.last?.timeStamp ?? 0
switch polarGyroData {
case let .gyroOfflineRecordingData(existingData, startTime, existingSettings):
let newSamples = existingData.samples + gyroData.samples.map { (timeStamp: $0.timeStamp, x: $0.x, y: $0.y, z: $0.z) }
Expand All @@ -1323,6 +1327,7 @@ extension PolarBleApiImpl: PolarBleApi {
observer.onNext(polarGyroData!)
}
case let magData as MagData:
lastTimestamp = magData.samples.last?.timeStamp ?? 0
switch polarMagData {
case let .magOfflineRecordingData(existingData, startTime, existingSettings):
let newSamples = existingData.samples + magData.samples.map { (timeStamp: $0.timeStamp, x: $0.x, y: $0.y, z: $0.z) }
Expand All @@ -1341,6 +1346,7 @@ extension PolarBleApiImpl: PolarBleApi {
observer.onNext(polarMagData!)
}
case let ppgData as PpgData:
lastTimestamp = ppgData.samples.last?.timeStamp ?? 0
switch polarPpgData {
case let .ppgOfflineRecordingData(existingData, startTime, existingSettings):
let newSamples = existingData.samples + ppgData.samples.map { (timeStamp: $0.timeStamp, channelSamples: $0.ppgDataSamples) }
Expand Down
Loading

0 comments on commit e2d69bd

Please sign in to comment.