fix related to restrictreadings : fixing filter in Array for BgReading's - also for NightScout and Dexcom upload, if user enables/disables upload, then upload also most recent reading

This commit is contained in:
Johan Degraeve 2021-01-16 12:23:03 +01:00
parent 6e98be4da6
commit 0b2ef2589e
3 changed files with 87 additions and 37 deletions

View File

@ -121,56 +121,97 @@ extension Array where Element: GlucoseData {
extension Array where Element: BgReading {
/// - Filter out readings that are too close to each other
/// - BgReadings array must be sorted by timeStamp of the BgReading, ascending, ie youngest first
/// - BgReadings array must be sorted by timeStamp of the BgReading, ascending, ie most recent reading is at index 0
/// - parameters:
/// - minimumTimeBetweenTwoReadingsInMinutes : filter out readings that are to close to each other in time, minimum difference in time between two readings = minimumTimeBetweenTwoReadingsInMinutes
/// - lastConnectionStatusChangeTimeStamp : lastConnectionStatusChangeTimeStamp > timeStampLastProcessedBgReading then the first connection will be returned, even if it's less than minimumTimeBetweenTwoReadingsInMinutes away from timeStampLastProcessedBgReading
/// - timeStampLastProcessedBgReading : only readings younger than timeStampLastProcessedBgReading will be returned, if nil then this check is not done
/// - lastConnectionStatusChangeTimeStamp : if lastConnectionStatusChangeTimeStamp > timeStampLastProcessedBgReading then the most recent reading will be returned, even if it's less than minimumTimeBetweenTwoReadingsInMinutes away from timeStampLastProcessedBgReading
/// - returns
/// filtered array, with readings at least minimumTimeBetweenTwoReadingsInMinutes away from each other
func filter(minimumTimeBetweenTwoReadingsInMinutes: Double, lastConnectionStatusChangeTimeStamp: Date?, timeStampLastProcessedBgReading: Date?) -> [BgReading] {
var didCheckLastConnectionStatusChangeTimeStamp = false
var timeStampLatestCheckedReading = timeStampLastProcessedBgReading
// initialise returnValue with empty array
var returnValue = [BgReading]()
// create a copy of self, reversed, because the filter algorithm assumes the first is the oldest element, while self is order by youngest first
var arrayReversed = Array(self.reversed())
// do the required filtering
arrayReversed = arrayReversed.filter({
// if most recent reading is either the minimum time away from the last processed reading or if there's been a disconnect after the last processed reading then add the most recent reading
// but first let's see if there's at least one reading
if let first = self.first {
if let lastConnectionStatusChangeTimeStamp = lastConnectionStatusChangeTimeStamp, let timeStampLastProcessedBgReading = timeStampLastProcessedBgReading, !didCheckLastConnectionStatusChangeTimeStamp {
if let timeStampLastProcessedBgReading = timeStampLastProcessedBgReading {
// if there was a disconnect or reconnect after the latest processed reading, and $0.timestamp (ie reading being processed) is after lastConnectionStatusChangeTimeStamp then add the reading
if lastConnectionStatusChangeTimeStamp.timeIntervalSince(timeStampLastProcessedBgReading) > 0.0 && lastConnectionStatusChangeTimeStamp.timeIntervalSince($0.timeStamp) < 0.0 {
if first.timeStamp.timeIntervalSince(timeStampLastProcessedBgReading) > minimumTimeBetweenTwoReadingsInMinutes * 60.0 {
timeStampLatestCheckedReading = $0.timeStamp
// most recent reading is more than minimumTimeBetweenTwoReadingsInMinutes later than last processed reading, so let's add it
returnValue.append(first)
} else {
// most recent reading is less than minimumTimeBetweenTwoReadingsInMinutes later than last processed reading, but maybe there's been a disconnect/reconnect since the last processed reading
if let lastConnectionStatusChangeTimeStamp = lastConnectionStatusChangeTimeStamp {
if lastConnectionStatusChangeTimeStamp.timeIntervalSince(timeStampLastProcessedBgReading) > 0 {
didCheckLastConnectionStatusChangeTimeStamp = true
// there's been a disconnect/reconnect since the last processed reading
// add the most recent reading
returnValue.append(first)
}
}
}
return true
} else {
// timeStampLastProcessedBgReading is nil, so this is the first reading being processed ever, let's add it
returnValue.append(first)
}
}
// now let's see if first was added, and also if there's more readings to add
if returnValue.count > 0 {
// there's one reading in returnValue, it's the most recent reading in the original array
var timeStampLastAddedReading = returnValue[0].timeStamp
// iterate through the remaining readings
for reading in self {
// by checking id , we skip the first in self, because that one is already added
if reading.id != returnValue[0].id {
// if the reading is earler than timeStampLastProcessedBgReading then no further processing needed, this reading and also the following readings are older readings, older than timeStampLastProcessedBgReading
if let timeStampLastProcessedBgReading = timeStampLastProcessedBgReading {
if reading.timeStamp.timeIntervalSince(timeStampLastProcessedBgReading) < 0 {
break
}
}
// add the reading if
// - the reading is more than minimumTimeBetweenTwoReadingsInMinutes earlier than the last added reading
// and
// - the gap between last added reading and timeStampLastProcessedBgReading more than minimumTimeBetweenTwoReadingsInMinutes (otherwise we may be adding a reading in between last processed reading and last added reading even though these two are alrady less than minimumTimeBetweenTwoReadingsInMinutes minutes away from each other
if reading.timeStamp.timeIntervalSince(timeStampLastAddedReading) < -minimumTimeBetweenTwoReadingsInMinutes * 60.0 && abs(timeStampLastAddedReading.timeIntervalSince(timeStampLastProcessedBgReading != nil ? timeStampLastProcessedBgReading! : Date(timeIntervalSince1970: 0))) > minimumTimeBetweenTwoReadingsInMinutes * 60.0 {
returnValue.append(reading)
timeStampLastAddedReading = reading.timeStamp
}
}
}
var returnValue = true
if let timeStampLatestCheckedReading = timeStampLatestCheckedReading {
returnValue = $0.timeStamp.timeIntervalSince(timeStampLatestCheckedReading) > minimumTimeBetweenTwoReadingsInMinutes * 60.0
}
if returnValue {
timeStampLatestCheckedReading = $0.timeStamp
}
return returnValue
})
}
return Array(arrayReversed.reversed())
return returnValue
}

View File

@ -116,7 +116,8 @@ class DexcomShareUploadManager:NSObject {
if success {
trace("in observeValue, start upload", log: self.log, category: ConstantsLog.categoryDexcomShareUploadManager, type: .info)
self.upload(lastConnectionStatusChangeTimeStamp: nil)
// set lastConnectionStatusChangeTimeStamp to as late as possible, to make sure that the most recent reading is uploaded if user is testing the credentials
self.upload(lastConnectionStatusChangeTimeStamp: Date())
} else {
trace("in observeValue, Dexcom Share credential check failed", log: self.log, category: ConstantsLog.categoryDexcomShareUploadManager, type: .error)
@ -145,8 +146,10 @@ class DexcomShareUploadManager:NSObject {
if success {
trace("in observeValue, start upload", log: self.log, category: ConstantsLog.categoryDexcomShareUploadManager, type: .info)
self.upload(lastConnectionStatusChangeTimeStamp: nil)
// set lastConnectionStatusChangeTimeStamp to as late as possible, to make sure that the most recent reading is uploaded if user is testing the credentials
self.upload(lastConnectionStatusChangeTimeStamp: Date())
} else {
trace("in observeValue, Dexcom Share credential check failed", log: self.log, category: ConstantsLog.categoryDexcomShareUploadManager, type: .error)

View File

@ -76,7 +76,7 @@ public class NightScoutUploadManager:NSObject {
/// uploads latest BgReadings to NightScout, only if nightscout enabled, not master, url and key defined, if schedule enabled then check also schedule
/// - parameters:
/// - lastConnectionStatusChangeTimeStamp : when was the last transmitter dis/reconnect - if nil then 1 1 1970 is used
/// - lastConnectionStatusChangeTimeStamp : when was the last transmitter dis/reconnect
public func upload(lastConnectionStatusChangeTimeStamp: Date?) {
// check if NightScout is enabled
@ -149,7 +149,10 @@ public class NightScoutUploadManager:NSObject {
DispatchQueue.main.async {
self.callMessageHandler(withCredentialVerificationResult: success, error: error)
if success {
self.upload(lastConnectionStatusChangeTimeStamp: nil)
// set lastConnectionStatusChangeTimeStamp to as late as possible, to make sure that the most recent reading is uploaded if user is testing the credentials
self.upload(lastConnectionStatusChangeTimeStamp: Date())
} else {
trace("in observeValue, NightScout credential check failed", log: self.oslog, category: ConstantsLog.categoryNightScoutUploadManager, type: .info)
}
@ -171,7 +174,10 @@ public class NightScoutUploadManager:NSObject {
testNightScoutCredentials(apiKey: apiKey, siteURL: siteUrl, { (success, error) in
DispatchQueue.main.async {
if success {
self.upload(lastConnectionStatusChangeTimeStamp: nil)
// set lastConnectionStatusChangeTimeStamp to as late as possible, to make sure that the most recent reading is uploaded if user is testing the credentials
self.upload(lastConnectionStatusChangeTimeStamp: Date())
} else {
trace("in observeValue, NightScout credential check failed", log: self.oslog, category: ConstantsLog.categoryNightScoutUploadManager, type: .info)
}